From 1704e7356bd2a49995440a5fb9ab543c7b753e86 Mon Sep 17 00:00:00 2001 From: mostafa7171 Date: Sun, 18 Jan 2026 11:42:00 +0330 Subject: [PATCH] first push --- .env.local | 25 + .env.prod | 22 + .gitignore | 135 + Dockerfile | 59 + GateWay.py | 74 + HaChickenStore/__init__.py | 0 HaChickenStore/asgi.py | 14 + HaChickenStore/settings.py | 262 + HaChickenStore/urls.py | 29 + HaChickenStore/wsgi.py | 14 + Herds.xlsx | Bin 0 -> 85055 bytes Herds2.xlsx | Bin 0 -> 84468 bytes 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 | 19 + 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 | 608 + LiveStock/Rancher/filterset.py | 25 + LiveStock/Rancher/helpers.py | 110 + LiveStock/Rancher/serializers.py | 40 + LiveStock/Rancher/urls.py | 40 + 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 | 19 + LiveStock/migrations/0001_initial.py | 187 + LiveStock/migrations/0002_livestock.py | 43 + .../migrations/0003_auto_20250305_1353.py | 23 + .../migrations/0004_auto_20250305_1721.py | 28 + .../migrations/0005_auto_20250305_2028.py | 38 + .../migrations/0006_auto_20250306_0023.py | 23 + .../migrations/0007_auto_20250306_1213.py | 45 + .../migrations/0008_auto_20250307_0930.py | 23 + .../migrations/0009_auto_20250307_1059.py | 25 + .../migrations/0010_auto_20250307_1107.py | 48 + .../migrations/0011_auto_20250307_1322.py | 39 + .../migrations/0012_auto_20250307_2135.py | 47 + .../migrations/0013_auto_20250308_1617.py | 23 + .../migrations/0014_auto_20250309_1654.py | 33 + .../migrations/0015_auto_20250310_1820.py | 58 + .../migrations/0016_auto_20250311_1055.py | 23 + LiveStock/migrations/0017_posseller.py | 37 + LiveStock/migrations/0018_rancher_type.py | 18 + .../migrations/0019_auto_20250312_1429.py | 33 + .../migrations/0020_auto_20250312_1459.py | 23 + .../migrations/0021_auto_20250412_1613.py | 23 + .../migrations/0022_auto_20250528_1439.py | 38 + .../migrations/0023_auto_20250810_1134.py | 33 + LiveStock/migrations/__init__.py | 0 LiveStock/models.py | 372 + LiveStock/sms_management.py | 31 + LiveStock/tests.py | 3 + LiveStock/urls.py | 10 + LiveStock/views.py | 3 + README.md | 1 + RasadyaarBale/__init__.py | 0 RasadyaarBale/admin.py | 3 + RasadyaarBale/apps.py | 6 + RasadyaarBale/helper.py | 1 + RasadyaarBale/migrations/0001_initial.py | 39 + .../0002_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 + Users.xlsx | Bin 0 -> 92233 bytes 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 + 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 | 373 + .../migrations/0002_auto_20221204_1315.py | 39 + .../migrations/0003_auto_20221204_1402.py | 39 + .../migrations/0004_auto_20221211_0954.py | 39 + .../migrations/0005_auto_20221221_0001.py | 39 + .../migrations/0006_auto_20230603_2204.py | 66 + .../migrations/0007_auto_20230603_2209.py | 39 + .../migrations/0008_auto_20230720_1546.py | 39 + .../migrations/0009_auto_20230723_1343.py | 119 + .../migrations/0010_auto_20230726_0957.py | 134 + .../migrations/0011_auto_20230806_2224.py | 39 + .../migrations/0012_auto_20230827_1543.py | 39 + .../migrations/0013_auto_20231010_1504.py | 39 + .../migrations/0014_auto_20231112_1546.py | 74 + .../migrations/0015_auto_20231112_1551.py | 39 + .../migrations/0016_auto_20231205_1348.py | 39 + .../migrations/0017_auto_20231210_1416.py | 39 + .../migrations/0018_auto_20231211_2019.py | 39 + .../migrations/0019_auto_20231214_2314.py | 39 + .../migrations/0020_auto_20240108_1233.py | 39 + .../migrations/0021_auto_20240110_2021.py | 39 + .../migrations/0022_auto_20240131_1501.py | 45 + .../migrations/0023_auto_20240220_1536.py | 39 + .../migrations/0024_auto_20240407_1100.py | 61 + .../migrations/0025_auto_20240416_1516.py | 39 + .../migrations/0026_auto_20240417_1455.py | 44 + .../migrations/0027_auto_20240420_0047.py | 39 + .../migrations/0028_auto_20240427_1523.py | 44 + .../migrations/0029_auto_20240513_1607.py | 39 + .../migrations/0030_auto_20240516_1516.py | 45 + .../migrations/0031_auto_20240518_0955.py | 74 + .../migrations/0032_auto_20240527_1504.py | 44 + .../migrations/0033_auto_20240620_1609.py | 39 + .../migrations/0034_auto_20240713_1535.py | 39 + .../migrations/0035_auto_20240803_1454.py | 39 + .../migrations/0036_auto_20240820_1051.py | 39 + .../migrations/0037_auto_20241031_1409.py | 39 + .../migrations/0038_auto_20241109_2158.py | 39 + .../migrations/0039_auto_20241201_1016.py | 183 + .../migrations/0040_auto_20241208_1514.py | 39 + .../migrations/0041_auto_20241227_1500.py | 39 + .../migrations/0042_auto_20241227_1519.py | 39 + .../migrations/0043_auto_20241227_1534.py | 39 + .../migrations/0044_auto_20241228_1054.py | 39 + .../migrations/0045_auto_20250112_1928.py | 39 + .../migrations/0046_auto_20250118_1751.py | 39 + .../migrations/0047_auto_20250121_0922.py | 79 + .../migrations/0048_auto_20250201_1221.py | 39 + .../migrations/0049_auto_20250303_2034.py | 39 + .../migrations/0050_auto_20250303_2036.py | 39 + .../migrations/0051_auto_20250306_1213.py | 39 + .../migrations/0052_auto_20250527_1054.py | 39 + .../migrations/0053_auto_20250527_1202.py | 39 + .../migrations/0054_auto_20250528_1439.py | 39 + .../migrations/0055_auto_20250601_1035.py | 39 + .../migrations/0056_auto_20250901_1650.py | 39 + .../migrations/0057_auto_20250920_1316.py | 39 + .../migrations/0058_auto_20251104_2046.py | 54 + .../migrations/0059_auto_20251208_1019.py | 39 + .../migrations/0060_auto_20251213_1627.py | 44 + .../migrations/0061_auto_20251214_2351.py | 39 + .../migrations/0062_auto_20251217_1642.py | 39 + authentication/migrations/__init__.py | 0 authentication/models.py | 548 + authentication/permission_views.py | 75 + authentication/permissions.py | 329 + authentication/register.py | 4444 ++ authentication/sahandsms/__init__.py | 0 authentication/sahandsms/sms.py | 588 + authentication/serializer/__init__.py | 0 authentication/serializer/serializer.py | 308 + authentication/serializers.py | 104 + authentication/sms_management.py | 3245 ++ authentication/tests.py | 3 + authentication/urls.py | 235 + authentication/views.py | 3163 ++ bot_eata.py | 1855 + cancel_bar_and_provice_request.py | 15 + cancel_out_provice.py | 16 + cron.py | 24 + cron_bad_transactions.py | 9 + cron_gid.py | 20 + cron_out_province_request.py | 19 + cron_report.py | 12 + cron_return_archive.py | 11 + cron_sms.py | 17 + cron_then_am.py | 11 + delete_kill_request_cron.py | 11 + deposit_id.py | 26 + deposit_percent.py | 13 + docker-compose.yml | 7 + every_12_hours.py | 15 + general_urls.py | 11 + helper_eata.py | 3 + 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_20250303_2034.py | 39 + .../migrations/0003_dashboardnotification.py | 38 + 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 | 2134 + panel/KillHouse/serializers.py | 6036 +++ panel/KillHouse/views.py | 19753 ++++++++ panel/ProvinceOperator/__init__.py | 0 panel/ProvinceOperator/excel_processing.py | 25023 ++++++++++ panel/ProvinceOperator/helpers.py | 284 + panel/ProvinceOperator/serializers.py | 6381 +++ panel/ProvinceOperator/services/__init__.py | 0 .../services/pos_transfer_service.py | 71 + panel/ProvinceOperator/views.py | 27767 +++++++++++ panel/ReportingPanel/__init__.py | 0 panel/ReportingPanel/excel_output.py | 174 + panel/ReportingPanel/filterset.py | 61 + panel/ReportingPanel/helper.py | 179 + panel/ReportingPanel/models.py | 10 + panel/ReportingPanel/serializer.py | 1873 + panel/ReportingPanel/views.py | 9339 ++++ 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 | 38247 ++++++++++++++++ panel/filterset.py | 646 + panel/helper.py | 254 + panel/helper_excel.py | 537 + 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 | 363 + panel/migrations/0001_initial.py | 1383 + panel/migrations/0002_auto_20221204_1315.py | 54 + panel/migrations/0003_auto_20221204_1402.py | 54 + panel/migrations/0004_auto_20221211_0954.py | 66 + panel/migrations/0005_auto_20221212_0953.py | 59 + panel/migrations/0006_auto_20221221_0001.py | 186 + panel/migrations/0007_auto_20221221_0827.py | 54 + panel/migrations/0008_auto_20221224_2319.py | 59 + panel/migrations/0009_auto_20221224_2325.py | 59 + panel/migrations/0010_auto_20221231_1052.py | 64 + panel/migrations/0011_auto_20230108_2316.py | 120 + panel/migrations/0012_auto_20230130_1648.py | 252 + panel/migrations/0013_auto_20230212_1532.py | 59 + panel/migrations/0014_auto_20230603_2204.py | 978 + panel/migrations/0015_auto_20230603_2209.py | 59 + panel/migrations/0016_auto_20230603_2210.py | 59 + panel/migrations/0017_auto_20230620_2120.py | 245 + panel/migrations/0018_auto_20230622_1035.py | 69 + panel/migrations/0019_auto_20230720_1546.py | 1228 + panel/migrations/0020_auto_20230723_1343.py | 869 + panel/migrations/0021_auto_20230726_0957.py | 64 + panel/migrations/0022_auto_20230806_2224.py | 227 + panel/migrations/0023_auto_20230807_1546.py | 69 + panel/migrations/0024_auto_20230810_1359.py | 136 + panel/migrations/0025_auto_20230810_1501.py | 64 + panel/migrations/0026_auto_20230817_1518.py | 131 + panel/migrations/0027_auto_20230820_1525.py | 74 + panel/migrations/0028_auto_20230821_1514.py | 69 + panel/migrations/0029_auto_20230827_1543.py | 104 + panel/migrations/0030_auto_20230831_1545.py | 87 + panel/migrations/0031_auto_20230902_1110.py | 59 + panel/migrations/0032_auto_20230902_1526.py | 64 + panel/migrations/0033_auto_20230904_1058.py | 64 + panel/migrations/0034_auto_20230911_1543.py | 98 + panel/migrations/0035_auto_20230912_1431.py | 64 + panel/migrations/0036_auto_20230927_1031.py | 90 + panel/migrations/0037_auto_20230927_1508.py | 74 + panel/migrations/0038_auto_20230928_1547.py | 106 + panel/migrations/0039_auto_20231002_1559.py | 69 + panel/migrations/0040_auto_20231004_1615.py | 121 + panel/migrations/0041_auto_20231007_1416.py | 64 + panel/migrations/0042_auto_20231010_1504.py | 105 + panel/migrations/0043_auto_20231012_0852.py | 96 + panel/migrations/0044_auto_20231018_1446.py | 79 + panel/migrations/0045_auto_20231029_1833.py | 82 + panel/migrations/0046_auto_20231031_1821.py | 79 + panel/migrations/0047_auto_20231103_1549.py | 64 + panel/migrations/0048_auto_20231104_1456.py | 79 + panel/migrations/0049_auto_20231105_2224.py | 64 + panel/migrations/0050_auto_20231107_1925.py | 91 + panel/migrations/0051_auto_20231108_1546.py | 70 + panel/migrations/0052_auto_20231111_1604.py | 69 + panel/migrations/0053_auto_20231113_1424.py | 64 + panel/migrations/0054_auto_20231117_1138.py | 59 + panel/migrations/0055_auto_20231122_1549.py | 69 + panel/migrations/0056_auto_20231127_1533.py | 129 + panel/migrations/0057_auto_20231130_1506.py | 95 + panel/migrations/0058_auto_20231205_1348.py | 84 + panel/migrations/0059_auto_20231210_1416.py | 129 + panel/migrations/0060_auto_20231211_2019.py | 133 + panel/migrations/0061_auto_20231212_1952.py | 90 + panel/migrations/0062_auto_20231214_2314.py | 85 + panel/migrations/0063_auto_20231217_1424.py | 110 + panel/migrations/0064_auto_20231225_1748.py | 64 + panel/migrations/0065_auto_20231226_1618.py | 64 + panel/migrations/0066_auto_20231227_1558.py | 137 + panel/migrations/0067_auto_20240102_1532.py | 115 + panel/migrations/0068_auto_20240103_1635.py | 111 + panel/migrations/0069_auto_20240108_1233.py | 171 + panel/migrations/0070_auto_20240108_2153.py | 64 + panel/migrations/0071_auto_20240108_2302.py | 64 + panel/migrations/0072_auto_20240108_2351.py | 81 + panel/migrations/0073_auto_20240109_1537.py | 99 + panel/migrations/0074_auto_20240110_2021.py | 109 + panel/migrations/0075_auto_20240111_1601.py | 64 + panel/migrations/0076_auto_20240114_1420.py | 64 + panel/migrations/0077_auto_20240114_1535.py | 69 + panel/migrations/0078_auto_20240115_1312.py | 64 + panel/migrations/0079_auto_20240117_1827.py | 59 + panel/migrations/0080_auto_20240118_1530.py | 64 + panel/migrations/0081_auto_20240121_1526.py | 69 + panel/migrations/0082_auto_20240123_1602.py | 108 + panel/migrations/0083_auto_20240127_1542.py | 69 + panel/migrations/0084_auto_20240130_1115.py | 95 + panel/migrations/0085_auto_20240206_1006.py | 64 + panel/migrations/0086_auto_20240206_1550.py | 75 + panel/migrations/0087_auto_20240207_1537.py | 73 + panel/migrations/0088_auto_20240214_0957.py | 59 + panel/migrations/0089_auto_20240214_1000.py | 64 + panel/migrations/0090_auto_20240214_1203.py | 79 + panel/migrations/0091_auto_20240220_1536.py | 106 + panel/migrations/0092_auto_20240221_1534.py | 115 + panel/migrations/0093_auto_20240226_1550.py | 69 + panel/migrations/0094_auto_20240227_1032.py | 109 + panel/migrations/0095_auto_20240227_1550.py | 69 + panel/migrations/0096_auto_20240304_0929.py | 69 + panel/migrations/0097_auto_20240309_1145.py | 89 + panel/migrations/0098_auto_20240311_1344.py | 64 + panel/migrations/0099_auto_20240312_1205.py | 88 + panel/migrations/0100_auto_20240315_2226.py | 80 + ...ll_house_assignment_limitation_and_more.py | 1457 + panel/migrations/0102_auto_20240409_1239.py | 81 + panel/migrations/0103_auto_20240413_1450.py | 88 + panel/migrations/0104_auto_20240414_1343.py | 104 + panel/migrations/0105_auto_20240416_1516.py | 104 + panel/migrations/0106_auto_20240417_1456.py | 88 + panel/migrations/0107_auto_20240418_1542.py | 69 + panel/migrations/0108_auto_20240420_0047.py | 84 + panel/migrations/0109_auto_20240420_1621.py | 81 + panel/migrations/0110_auto_20240427_1523.py | 64 + panel/migrations/0111_auto_20240429_1320.py | 90 + panel/migrations/0112_auto_20240430_1548.py | 85 + panel/migrations/0113_auto_20240506_1514.py | 115 + panel/migrations/0114_auto_20240507_1538.py | 64 + panel/migrations/0115_auto_20240508_1038.py | 69 + panel/migrations/0116_auto_20240508_1355.py | 79 + panel/migrations/0117_auto_20240513_1607.py | 130 + panel/migrations/0118_auto_20240515_1335.py | 84 + panel/migrations/0119_auto_20240516_1515.py | 297 + panel/migrations/0120_auto_20240518_0955.py | 209 + panel/migrations/0121_auto_20240521_1101.py | 74 + panel/migrations/0122_auto_20240523_1606.py | 64 + panel/migrations/0123_auto_20240525_1509.py | 69 + panel/migrations/0124_auto_20240528_1328.py | 69 + panel/migrations/0125_auto_20240605_1321.py | 190 + panel/migrations/0126_auto_20240605_1903.py | 64 + panel/migrations/0127_auto_20240606_1500.py | 69 + panel/migrations/0128_auto_20240609_2150.py | 102 + panel/migrations/0129_auto_20240612_1623.py | 101 + panel/migrations/0130_auto_20240620_1609.py | 227 + panel/migrations/0131_auto_20240622_1529.py | 84 + panel/migrations/0132_auto_20240623_1242.py | 64 + panel/migrations/0133_auto_20240626_1705.py | 64 + panel/migrations/0134_auto_20240629_1542.py | 91 + panel/migrations/0135_auto_20240630_1545.py | 135 + panel/migrations/0136_auto_20240701_1548.py | 64 + panel/migrations/0137_auto_20240702_1601.py | 93 + panel/migrations/0138_auto_20240703_1546.py | 96 + panel/migrations/0139_auto_20240706_1536.py | 81 + panel/migrations/0140_auto_20240707_1529.py | 117 + panel/migrations/0141_auto_20240713_0930.py | 109 + panel/migrations/0142_auto_20240713_1405.py | 112 + panel/migrations/0143_auto_20240713_1433.py | 90 + panel/migrations/0144_auto_20240713_1535.py | 104 + panel/migrations/0145_auto_20240720_1456.py | 159 + panel/migrations/0146_auto_20240724_1518.py | 64 + panel/migrations/0147_auto_20240725_1447.py | 84 + panel/migrations/0148_auto_20240727_1139.py | 64 + panel/migrations/0149_auto_20240803_1454.py | 115 + panel/migrations/0150_auto_20240804_1413.py | 75 + panel/migrations/0151_auto_20240805_1422.py | 74 + panel/migrations/0152_auto_20240807_1448.py | 64 + panel/migrations/0153_auto_20240808_1331.py | 107 + panel/migrations/0154_auto_20240810_1440.py | 269 + panel/migrations/0155_auto_20240813_1029.py | 79 + panel/migrations/0156_auto_20240819_1458.py | 121 + panel/migrations/0157_auto_20240820_1051.py | 83 + panel/migrations/0158_auto_20240821_1445.py | 64 + panel/migrations/0159_auto_20240826_1453.py | 79 + panel/migrations/0160_auto_20240829_1344.py | 59 + panel/migrations/0161_auto_20240831_0932.py | 69 + panel/migrations/0162_auto_20240912_1203.py | 124 + panel/migrations/0163_auto_20241014_0957.py | 154 + panel/migrations/0164_auto_20241016_1031.py | 63 + panel/migrations/0165_auto_20241016_1111.py | 64 + panel/migrations/0166_auto_20241017_1246.py | 64 + panel/migrations/0167_auto_20241022_1158.py | 79 + panel/migrations/0168_auto_20241022_1200.py | 64 + panel/migrations/0169_auto_20241023_1331.py | 99 + panel/migrations/0170_auto_20241024_0937.py | 64 + panel/migrations/0171_auto_20241026_0958.py | 69 + panel/migrations/0172_auto_20241026_1356.py | 64 + panel/migrations/0173_auto_20241031_1409.py | 108 + panel/migrations/0174_auto_20241103_0818.py | 78 + panel/migrations/0175_auto_20241103_1105.py | 64 + panel/migrations/0176_auto_20241103_1110.py | 63 + panel/migrations/0177_auto_20241103_1114.py | 64 + panel/migrations/0178_auto_20241103_1120.py | 63 + panel/migrations/0179_auto_20241109_1604.py | 79 + panel/migrations/0180_auto_20241109_2044.py | 69 + panel/migrations/0181_auto_20241109_2158.py | 66 + panel/migrations/0182_auto_20241109_2159.py | 63 + panel/migrations/0183_auto_20241109_2203.py | 59 + panel/migrations/0184_auto_20241109_2208.py | 64 + panel/migrations/0185_auto_20241110_1129.py | 64 + panel/migrations/0186_auto_20241110_1433.py | 68 + panel/migrations/0187_auto_20241110_2303.py | 64 + panel/migrations/0188_auto_20241112_1550.py | 69 + panel/migrations/0189_auto_20241116_2114.py | 99 + panel/migrations/0190_auto_20241117_1117.py | 85 + panel/migrations/0191_auto_20241117_1124.py | 64 + panel/migrations/0192_auto_20241119_1120.py | 64 + panel/migrations/0193_auto_20241120_0826.py | 64 + panel/migrations/0194_auto_20241126_1925.py | 438 + panel/migrations/0195_auto_20241126_1928.py | 65 + panel/migrations/0196_auto_20241127_1001.py | 79 + panel/migrations/0197_auto_20241201_1026.py | 1155 + panel/migrations/0198_auto_20241203_1130.py | 68 + panel/migrations/0199_auto_20241203_1240.py | 64 + panel/migrations/0200_auto_20241204_1557.py | 103 + panel/migrations/0201_auto_20241208_1125.py | 99 + panel/migrations/0202_auto_20241208_1514.py | 84 + panel/migrations/0203_auto_20241209_1548.py | 69 + panel/migrations/0204_auto_20241211_1500.py | 85 + panel/migrations/0205_auto_20241214_1645.py | 79 + panel/migrations/0206_auto_20241216_1353.py | 65 + panel/migrations/0207_auto_20241218_1015.py | 89 + panel/migrations/0208_auto_20241218_1441.py | 64 + panel/migrations/0209_auto_20241222_1149.py | 121 + panel/migrations/0210_auto_20241225_1127.py | 113 + panel/migrations/0211_auto_20241225_1631.py | 83 + panel/migrations/0212_auto_20241231_1547.py | 74 + panel/migrations/0213_auto_20241231_2151.py | 92 + panel/migrations/0214_auto_20250107_0934.py | 75 + panel/migrations/0215_auto_20250107_1815.py | 85 + panel/migrations/0216_auto_20250112_1928.py | 119 + panel/migrations/0217_auto_20250113_1620.py | 75 + panel/migrations/0218_auto_20250120_1050.py | 80 + panel/migrations/0219_auto_20250201_1511.py | 138 + panel/migrations/0220_auto_20250205_1307.py | 75 + panel/migrations/0221_auto_20250209_0939.py | 74 + panel/migrations/0222_auto_20250209_1613.py | 95 + panel/migrations/0223_auto_20250210_1600.py | 109 + panel/migrations/0224_auto_20250211_1239.py | 74 + panel/migrations/0225_auto_20250212_0919.py | 89 + panel/migrations/0226_auto_20250212_0946.py | 85 + panel/migrations/0227_auto_20250212_0949.py | 89 + panel/migrations/0228_auto_20250212_1728.py | 98 + panel/migrations/0229_auto_20250212_1730.py | 79 + panel/migrations/0230_auto_20250216_1323.py | 104 + panel/migrations/0231_auto_20250222_1151.py | 154 + panel/migrations/0232_auto_20250223_1025.py | 92 + panel/migrations/0233_auto_20250223_1547.py | 79 + panel/migrations/0234_auto_20250224_1402.py | 80 + panel/migrations/0235_auto_20250224_1407.py | 76 + panel/migrations/0236_auto_20250224_1528.py | 79 + panel/migrations/0237_auto_20250225_1158.py | 103 + panel/migrations/0238_auto_20250226_0946.py | 74 + panel/migrations/0239_auto_20250303_2034.py | 69 + panel/migrations/0240_auto_20250303_2036.py | 69 + panel/migrations/0241_auto_20250304_1734.py | 106 + panel/migrations/0242_auto_20250307_1727.py | 74 + panel/migrations/0243_auto_20250317_0032.py | 89 + panel/migrations/0244_auto_20250414_1439.py | 89 + panel/migrations/0245_auto_20250420_1113.py | 74 + panel/migrations/0246_auto_20250430_1317.py | 94 + panel/migrations/0247_auto_20250503_1405.py | 96 + panel/migrations/0248_auto_20250504_1447.py | 91 + panel/migrations/0249_auto_20250505_1511.py | 79 + panel/migrations/0250_auto_20250506_1102.py | 74 + panel/migrations/0251_auto_20250510_1213.py | 84 + panel/migrations/0252_auto_20250511_1501.py | 74 + panel/migrations/0253_auto_20250517_0916.py | 74 + panel/migrations/0254_auto_20250518_0912.py | 89 + panel/migrations/0255_auto_20250518_1229.py | 74 + panel/migrations/0256_auto_20250520_1146.py | 74 + panel/migrations/0257_auto_20250526_1029.py | 103 + panel/migrations/0258_auto_20250527_1054.py | 69 + panel/migrations/0259_auto_20250527_1249.py | 119 + panel/migrations/0260_auto_20250528_1439.py | 93 + panel/migrations/0261_auto_20250531_1003.py | 89 + panel/migrations/0262_auto_20250531_1016.py | 74 + panel/migrations/0263_auto_20250531_1131.py | 74 + panel/migrations/0264_auto_20250531_1211.py | 84 + panel/migrations/0265_auto_20250531_1633.py | 74 + panel/migrations/0266_auto_20250601_1035.py | 93 + panel/migrations/0267_auto_20250603_1610.py | 85 + panel/migrations/0268_auto_20250607_1633.py | 101 + panel/migrations/0269_auto_20250610_1356.py | 130 + panel/migrations/0270_auto_20250628_1430.py | 74 + panel/migrations/0271_auto_20250628_1505.py | 74 + panel/migrations/0272_auto_20250707_1154.py | 92 + panel/migrations/0273_auto_20250708_1044.py | 84 + panel/migrations/0274_auto_20250708_1615.py | 109 + panel/migrations/0275_auto_20250709_1624.py | 74 + panel/migrations/0276_auto_20250713_1430.py | 74 + panel/migrations/0277_auto_20250714_1049.py | 89 + panel/migrations/0278_auto_20250714_1102.py | 74 + panel/migrations/0279_auto_20250719_0909.py | 74 + panel/migrations/0280_auto_20250719_0942.py | 74 + panel/migrations/0281_auto_20250721_1055.py | 95 + panel/migrations/0282_auto_20250722_1259.py | 104 + panel/migrations/0283_auto_20250723_1031.py | 89 + panel/migrations/0284_auto_20250727_0802.py | 75 + panel/migrations/0285_auto_20250729_1146.py | 135 + panel/migrations/0286_auto_20250803_0824.py | 79 + panel/migrations/0287_auto_20250805_0855.py | 75 + panel/migrations/0288_auto_20250806_1157.py | 139 + panel/migrations/0289_auto_20250807_1008.py | 104 + panel/migrations/0290_auto_20250809_0952.py | 89 + panel/migrations/0291_auto_20250809_1023.py | 74 + panel/migrations/0292_auto_20250809_1239.py | 74 + panel/migrations/0293_auto_20250809_1524.py | 94 + panel/migrations/0294_auto_20250810_1420.py | 162 + panel/migrations/0295_auto_20250817_0854.py | 74 + panel/migrations/0296_auto_20250817_0947.py | 91 + panel/migrations/0297_auto_20250817_1031.py | 74 + panel/migrations/0298_auto_20250817_1051.py | 84 + panel/migrations/0299_auto_20250817_1358.py | 74 + panel/migrations/0300_auto_20250818_0950.py | 83 + panel/migrations/0301_auto_20250820_1154.py | 74 + panel/migrations/0302_auto_20250825_0835.py | 74 + panel/migrations/0303_auto_20250825_1630.py | 89 + panel/migrations/0304_auto_20250826_0920.py | 91 + panel/migrations/0305_auto_20250826_0948.py | 74 + panel/migrations/0306_auto_20250827_1019.py | 74 + panel/migrations/0307_auto_20250827_1701.py | 92 + panel/migrations/0308_auto_20250829_0153.py | 84 + panel/migrations/0309_auto_20250830_1026.py | 74 + panel/migrations/0310_auto_20250831_1016.py | 84 + panel/migrations/0311_auto_20250901_0929.py | 91 + panel/migrations/0312_auto_20250901_1650.py | 91 + panel/migrations/0313_auto_20250902_1217.py | 89 + panel/migrations/0314_auto_20250902_1659.py | 94 + panel/migrations/0315_auto_20250907_0855.py | 89 + panel/migrations/0316_auto_20250914_1106.py | 94 + panel/migrations/0317_auto_20250914_1455.py | 79 + panel/migrations/0318_auto_20250915_0911.py | 74 + panel/migrations/0319_auto_20250915_1606.py | 75 + panel/migrations/0320_auto_20250916_0847.py | 79 + panel/migrations/0321_auto_20250916_0941.py | 94 + panel/migrations/0322_auto_20250916_1053.py | 74 + panel/migrations/0323_auto_20250916_1433.py | 94 + panel/migrations/0324_auto_20250920_0949.py | 84 + panel/migrations/0325_auto_20250920_1316.py | 82 + panel/migrations/0326_auto_20250922_0914.py | 213 + panel/migrations/0327_auto_20250922_1054.py | 74 + panel/migrations/0328_auto_20250922_1350.py | 119 + panel/migrations/0329_auto_20250924_1349.py | 84 + panel/migrations/0330_auto_20250924_1430.py | 99 + panel/migrations/0331_auto_20250925_1052.py | 74 + panel/migrations/0332_auto_20250925_1109.py | 79 + panel/migrations/0333_auto_20250925_1659.py | 154 + panel/migrations/0334_auto_20250927_2226.py | 105 + panel/migrations/0335_auto_20250929_1508.py | 74 + panel/migrations/0336_auto_20251001_0930.py | 121 + panel/migrations/0337_auto_20251001_1131.py | 74 + panel/migrations/0338_auto_20251004_1109.py | 80 + panel/migrations/0339_auto_20251005_1501.py | 390 + panel/migrations/0340_auto_20251006_0851.py | 79 + panel/migrations/0341_auto_20251006_0908.py | 79 + panel/migrations/0342_auto_20251006_1459.py | 74 + panel/migrations/0343_auto_20251007_1522.py | 111 + panel/migrations/0344_auto_20251007_1646.py | 74 + panel/migrations/0345_auto_20251008_1416.py | 79 + panel/migrations/0346_auto_20251012_1702.py | 79 + panel/migrations/0347_auto_20251021_1631.py | 229 + panel/migrations/0348_auto_20251022_1621.py | 79 + panel/migrations/0349_auto_20251025_1622.py | 109 + panel/migrations/0350_auto_20251026_2130.py | 79 + panel/migrations/0351_auto_20251027_1526.py | 104 + panel/migrations/0352_auto_20251028_1151.py | 74 + panel/migrations/0353_auto_20251028_1415.py | 74 + panel/migrations/0354_auto_20251029_1138.py | 101 + panel/migrations/0355_auto_20251029_1715.py | 79 + panel/migrations/0356_auto_20251102_1538.py | 104 + panel/migrations/0357_auto_20251102_1626.py | 74 + panel/migrations/0358_auto_20251102_2057.py | 69 + panel/migrations/0359_auto_20251102_2058.py | 91 + panel/migrations/0360_auto_20251103_1458.py | 94 + panel/migrations/0361_auto_20251103_1642.py | 104 + panel/migrations/0362_auto_20251104_1658.py | 114 + panel/migrations/0363_auto_20251105_1113.py | 84 + panel/migrations/0364_auto_20251109_1516.py | 90 + panel/migrations/0365_auto_20251110_1124.py | 148 + panel/migrations/0366_auto_20251111_0941.py | 93 + panel/migrations/0367_auto_20251111_1619.py | 74 + panel/migrations/0368_auto_20251115_1513.py | 142 + panel/migrations/0369_auto_20251116_1609.py | 329 + panel/migrations/0370_auto_20251125_1625.py | 85 + panel/migrations/0371_auto_20251130_1614.py | 74 + panel/migrations/0372_auto_20251202_1604.py | 93 + panel/migrations/0373_auto_20251203_1610.py | 100 + panel/migrations/0374_auto_20251208_1019.py | 91 + panel/migrations/0375_auto_20251213_1627.py | 197 + panel/migrations/0376_auto_20251214_2351.py | 80 + panel/migrations/0377_auto_20251215_1644.py | 117 + panel/migrations/0378_auto_20251216_1641.py | 147 + panel/migrations/0379_auto_20251217_1642.py | 436 + panel/migrations/0380_auto_20251221_1049.py | 180 + panel/migrations/__init__.py | 0 panel/models.py | 7484 +++ panel/pos_helper.py | 264 + 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 | 64 + panel/tests.py | 3 + panel/urls.py | 1397 + panel/validate_headers.py | 120 + panel/views.py | 77 + pdf/__init__.py | 0 pdf/views.py | 1635 + province_orderid.py | 5 + requirements.txt | 92 + 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/debt_report_pdf.png | Bin 0 -> 2033586 bytes static/assets/img/killhouse.png | Bin 0 -> 17403 bytes static/assets/img/poultry.png | Bin 0 -> 19073 bytes static/css/styles.css | 190 + static/css/styles_for_hatching_detail.css | 284 + ...ital_agreement_for_buying_and_selling.html | 259 + templates/base.html | 17 + templates/kill_house_debt_report.html | 174 + .../management_all_poultry_and_warehouse.html | 512 + templates/poultry_datail.html | 1485 + templates/poultry_science_report.html | 440 + 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 | 149 + ticket/migrations/0002_ticket_ticket_id.py | 18 + .../0003_messagesupport_ticketsupport.py | 52 + ticket/migrations/0004_auto_20241227_1534.py | 108 + ticket/migrations/0005_auto_20241228_1050.py | 50 + ...esupport_ticketpermission_ticketsupport.py | 68 + ticket/migrations/0007_messagesupport_file.py | 18 + ticket/migrations/0008_auto_20250118_1751.py | 24 + ticket/migrations/0009_auto_20250201_1221.py | 35 + ticket/migrations/0010_auto_20250525_0951.py | 26 + 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 + 723 files changed, 273450 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 HaChickenStore/__init__.py create mode 100644 HaChickenStore/asgi.py create mode 100644 HaChickenStore/settings.py create mode 100644 HaChickenStore/urls.py create mode 100644 HaChickenStore/wsgi.py create mode 100644 Herds.xlsx create mode 100644 Herds2.xlsx 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_livestock.py create mode 100644 LiveStock/migrations/0003_auto_20250305_1353.py create mode 100644 LiveStock/migrations/0004_auto_20250305_1721.py create mode 100644 LiveStock/migrations/0005_auto_20250305_2028.py create mode 100644 LiveStock/migrations/0006_auto_20250306_0023.py create mode 100644 LiveStock/migrations/0007_auto_20250306_1213.py create mode 100644 LiveStock/migrations/0008_auto_20250307_0930.py create mode 100644 LiveStock/migrations/0009_auto_20250307_1059.py create mode 100644 LiveStock/migrations/0010_auto_20250307_1107.py create mode 100644 LiveStock/migrations/0011_auto_20250307_1322.py create mode 100644 LiveStock/migrations/0012_auto_20250307_2135.py create mode 100644 LiveStock/migrations/0013_auto_20250308_1617.py create mode 100644 LiveStock/migrations/0014_auto_20250309_1654.py create mode 100644 LiveStock/migrations/0015_auto_20250310_1820.py create mode 100644 LiveStock/migrations/0016_auto_20250311_1055.py create mode 100644 LiveStock/migrations/0017_posseller.py create mode 100644 LiveStock/migrations/0018_rancher_type.py create mode 100644 LiveStock/migrations/0019_auto_20250312_1429.py create mode 100644 LiveStock/migrations/0020_auto_20250312_1459.py create mode 100644 LiveStock/migrations/0021_auto_20250412_1613.py create mode 100644 LiveStock/migrations/0022_auto_20250528_1439.py create mode 100644 LiveStock/migrations/0023_auto_20250810_1134.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_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 Users.xlsx 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/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_20221204_1315.py create mode 100644 authentication/migrations/0003_auto_20221204_1402.py create mode 100644 authentication/migrations/0004_auto_20221211_0954.py create mode 100644 authentication/migrations/0005_auto_20221221_0001.py create mode 100644 authentication/migrations/0006_auto_20230603_2204.py create mode 100644 authentication/migrations/0007_auto_20230603_2209.py create mode 100644 authentication/migrations/0008_auto_20230720_1546.py create mode 100644 authentication/migrations/0009_auto_20230723_1343.py create mode 100644 authentication/migrations/0010_auto_20230726_0957.py create mode 100644 authentication/migrations/0011_auto_20230806_2224.py create mode 100644 authentication/migrations/0012_auto_20230827_1543.py create mode 100644 authentication/migrations/0013_auto_20231010_1504.py create mode 100644 authentication/migrations/0014_auto_20231112_1546.py create mode 100644 authentication/migrations/0015_auto_20231112_1551.py create mode 100644 authentication/migrations/0016_auto_20231205_1348.py create mode 100644 authentication/migrations/0017_auto_20231210_1416.py create mode 100644 authentication/migrations/0018_auto_20231211_2019.py create mode 100644 authentication/migrations/0019_auto_20231214_2314.py create mode 100644 authentication/migrations/0020_auto_20240108_1233.py create mode 100644 authentication/migrations/0021_auto_20240110_2021.py create mode 100644 authentication/migrations/0022_auto_20240131_1501.py create mode 100644 authentication/migrations/0023_auto_20240220_1536.py create mode 100644 authentication/migrations/0024_auto_20240407_1100.py create mode 100644 authentication/migrations/0025_auto_20240416_1516.py create mode 100644 authentication/migrations/0026_auto_20240417_1455.py create mode 100644 authentication/migrations/0027_auto_20240420_0047.py create mode 100644 authentication/migrations/0028_auto_20240427_1523.py create mode 100644 authentication/migrations/0029_auto_20240513_1607.py create mode 100644 authentication/migrations/0030_auto_20240516_1516.py create mode 100644 authentication/migrations/0031_auto_20240518_0955.py create mode 100644 authentication/migrations/0032_auto_20240527_1504.py create mode 100644 authentication/migrations/0033_auto_20240620_1609.py create mode 100644 authentication/migrations/0034_auto_20240713_1535.py create mode 100644 authentication/migrations/0035_auto_20240803_1454.py create mode 100644 authentication/migrations/0036_auto_20240820_1051.py create mode 100644 authentication/migrations/0037_auto_20241031_1409.py create mode 100644 authentication/migrations/0038_auto_20241109_2158.py create mode 100644 authentication/migrations/0039_auto_20241201_1016.py create mode 100644 authentication/migrations/0040_auto_20241208_1514.py create mode 100644 authentication/migrations/0041_auto_20241227_1500.py create mode 100644 authentication/migrations/0042_auto_20241227_1519.py create mode 100644 authentication/migrations/0043_auto_20241227_1534.py create mode 100644 authentication/migrations/0044_auto_20241228_1054.py create mode 100644 authentication/migrations/0045_auto_20250112_1928.py create mode 100644 authentication/migrations/0046_auto_20250118_1751.py create mode 100644 authentication/migrations/0047_auto_20250121_0922.py create mode 100644 authentication/migrations/0048_auto_20250201_1221.py create mode 100644 authentication/migrations/0049_auto_20250303_2034.py create mode 100644 authentication/migrations/0050_auto_20250303_2036.py create mode 100644 authentication/migrations/0051_auto_20250306_1213.py create mode 100644 authentication/migrations/0052_auto_20250527_1054.py create mode 100644 authentication/migrations/0053_auto_20250527_1202.py create mode 100644 authentication/migrations/0054_auto_20250528_1439.py create mode 100644 authentication/migrations/0055_auto_20250601_1035.py create mode 100644 authentication/migrations/0056_auto_20250901_1650.py create mode 100644 authentication/migrations/0057_auto_20250920_1316.py create mode 100644 authentication/migrations/0058_auto_20251104_2046.py create mode 100644 authentication/migrations/0059_auto_20251208_1019.py create mode 100644 authentication/migrations/0060_auto_20251213_1627.py create mode 100644 authentication/migrations/0061_auto_20251214_2351.py create mode 100644 authentication/migrations/0062_auto_20251217_1642.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 cancel_out_provice.py create mode 100644 cron.py create mode 100644 cron_bad_transactions.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_sms.py create mode 100644 cron_then_am.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 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_20250303_2034.py create mode 100644 notification/migrations/0003_dashboardnotification.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_20221204_1315.py create mode 100644 panel/migrations/0003_auto_20221204_1402.py create mode 100644 panel/migrations/0004_auto_20221211_0954.py create mode 100644 panel/migrations/0005_auto_20221212_0953.py create mode 100644 panel/migrations/0006_auto_20221221_0001.py create mode 100644 panel/migrations/0007_auto_20221221_0827.py create mode 100644 panel/migrations/0008_auto_20221224_2319.py create mode 100644 panel/migrations/0009_auto_20221224_2325.py create mode 100644 panel/migrations/0010_auto_20221231_1052.py create mode 100644 panel/migrations/0011_auto_20230108_2316.py create mode 100644 panel/migrations/0012_auto_20230130_1648.py create mode 100644 panel/migrations/0013_auto_20230212_1532.py create mode 100644 panel/migrations/0014_auto_20230603_2204.py create mode 100644 panel/migrations/0015_auto_20230603_2209.py create mode 100644 panel/migrations/0016_auto_20230603_2210.py create mode 100644 panel/migrations/0017_auto_20230620_2120.py create mode 100644 panel/migrations/0018_auto_20230622_1035.py create mode 100644 panel/migrations/0019_auto_20230720_1546.py create mode 100644 panel/migrations/0020_auto_20230723_1343.py create mode 100644 panel/migrations/0021_auto_20230726_0957.py create mode 100644 panel/migrations/0022_auto_20230806_2224.py create mode 100644 panel/migrations/0023_auto_20230807_1546.py create mode 100644 panel/migrations/0024_auto_20230810_1359.py create mode 100644 panel/migrations/0025_auto_20230810_1501.py create mode 100644 panel/migrations/0026_auto_20230817_1518.py create mode 100644 panel/migrations/0027_auto_20230820_1525.py create mode 100644 panel/migrations/0028_auto_20230821_1514.py create mode 100644 panel/migrations/0029_auto_20230827_1543.py create mode 100644 panel/migrations/0030_auto_20230831_1545.py create mode 100644 panel/migrations/0031_auto_20230902_1110.py create mode 100644 panel/migrations/0032_auto_20230902_1526.py create mode 100644 panel/migrations/0033_auto_20230904_1058.py create mode 100644 panel/migrations/0034_auto_20230911_1543.py create mode 100644 panel/migrations/0035_auto_20230912_1431.py create mode 100644 panel/migrations/0036_auto_20230927_1031.py create mode 100644 panel/migrations/0037_auto_20230927_1508.py create mode 100644 panel/migrations/0038_auto_20230928_1547.py create mode 100644 panel/migrations/0039_auto_20231002_1559.py create mode 100644 panel/migrations/0040_auto_20231004_1615.py create mode 100644 panel/migrations/0041_auto_20231007_1416.py create mode 100644 panel/migrations/0042_auto_20231010_1504.py create mode 100644 panel/migrations/0043_auto_20231012_0852.py create mode 100644 panel/migrations/0044_auto_20231018_1446.py create mode 100644 panel/migrations/0045_auto_20231029_1833.py create mode 100644 panel/migrations/0046_auto_20231031_1821.py create mode 100644 panel/migrations/0047_auto_20231103_1549.py create mode 100644 panel/migrations/0048_auto_20231104_1456.py create mode 100644 panel/migrations/0049_auto_20231105_2224.py create mode 100644 panel/migrations/0050_auto_20231107_1925.py create mode 100644 panel/migrations/0051_auto_20231108_1546.py create mode 100644 panel/migrations/0052_auto_20231111_1604.py create mode 100644 panel/migrations/0053_auto_20231113_1424.py create mode 100644 panel/migrations/0054_auto_20231117_1138.py create mode 100644 panel/migrations/0055_auto_20231122_1549.py create mode 100644 panel/migrations/0056_auto_20231127_1533.py create mode 100644 panel/migrations/0057_auto_20231130_1506.py create mode 100644 panel/migrations/0058_auto_20231205_1348.py create mode 100644 panel/migrations/0059_auto_20231210_1416.py create mode 100644 panel/migrations/0060_auto_20231211_2019.py create mode 100644 panel/migrations/0061_auto_20231212_1952.py create mode 100644 panel/migrations/0062_auto_20231214_2314.py create mode 100644 panel/migrations/0063_auto_20231217_1424.py create mode 100644 panel/migrations/0064_auto_20231225_1748.py create mode 100644 panel/migrations/0065_auto_20231226_1618.py create mode 100644 panel/migrations/0066_auto_20231227_1558.py create mode 100644 panel/migrations/0067_auto_20240102_1532.py create mode 100644 panel/migrations/0068_auto_20240103_1635.py create mode 100644 panel/migrations/0069_auto_20240108_1233.py create mode 100644 panel/migrations/0070_auto_20240108_2153.py create mode 100644 panel/migrations/0071_auto_20240108_2302.py create mode 100644 panel/migrations/0072_auto_20240108_2351.py create mode 100644 panel/migrations/0073_auto_20240109_1537.py create mode 100644 panel/migrations/0074_auto_20240110_2021.py create mode 100644 panel/migrations/0075_auto_20240111_1601.py create mode 100644 panel/migrations/0076_auto_20240114_1420.py create mode 100644 panel/migrations/0077_auto_20240114_1535.py create mode 100644 panel/migrations/0078_auto_20240115_1312.py create mode 100644 panel/migrations/0079_auto_20240117_1827.py create mode 100644 panel/migrations/0080_auto_20240118_1530.py create mode 100644 panel/migrations/0081_auto_20240121_1526.py create mode 100644 panel/migrations/0082_auto_20240123_1602.py create mode 100644 panel/migrations/0083_auto_20240127_1542.py create mode 100644 panel/migrations/0084_auto_20240130_1115.py create mode 100644 panel/migrations/0085_auto_20240206_1006.py create mode 100644 panel/migrations/0086_auto_20240206_1550.py create mode 100644 panel/migrations/0087_auto_20240207_1537.py create mode 100644 panel/migrations/0088_auto_20240214_0957.py create mode 100644 panel/migrations/0089_auto_20240214_1000.py create mode 100644 panel/migrations/0090_auto_20240214_1203.py create mode 100644 panel/migrations/0091_auto_20240220_1536.py create mode 100644 panel/migrations/0092_auto_20240221_1534.py create mode 100644 panel/migrations/0093_auto_20240226_1550.py create mode 100644 panel/migrations/0094_auto_20240227_1032.py create mode 100644 panel/migrations/0095_auto_20240227_1550.py create mode 100644 panel/migrations/0096_auto_20240304_0929.py create mode 100644 panel/migrations/0097_auto_20240309_1145.py create mode 100644 panel/migrations/0098_auto_20240311_1344.py create mode 100644 panel/migrations/0099_auto_20240312_1205.py create mode 100644 panel/migrations/0100_auto_20240315_2226.py create mode 100644 panel/migrations/0101_operationlimitation_vet_check_kill_house_assignment_limitation_and_more.py create mode 100644 panel/migrations/0102_auto_20240409_1239.py create mode 100644 panel/migrations/0103_auto_20240413_1450.py create mode 100644 panel/migrations/0104_auto_20240414_1343.py create mode 100644 panel/migrations/0105_auto_20240416_1516.py create mode 100644 panel/migrations/0106_auto_20240417_1456.py create mode 100644 panel/migrations/0107_auto_20240418_1542.py create mode 100644 panel/migrations/0108_auto_20240420_0047.py create mode 100644 panel/migrations/0109_auto_20240420_1621.py create mode 100644 panel/migrations/0110_auto_20240427_1523.py create mode 100644 panel/migrations/0111_auto_20240429_1320.py create mode 100644 panel/migrations/0112_auto_20240430_1548.py create mode 100644 panel/migrations/0113_auto_20240506_1514.py create mode 100644 panel/migrations/0114_auto_20240507_1538.py create mode 100644 panel/migrations/0115_auto_20240508_1038.py create mode 100644 panel/migrations/0116_auto_20240508_1355.py create mode 100644 panel/migrations/0117_auto_20240513_1607.py create mode 100644 panel/migrations/0118_auto_20240515_1335.py create mode 100644 panel/migrations/0119_auto_20240516_1515.py create mode 100644 panel/migrations/0120_auto_20240518_0955.py create mode 100644 panel/migrations/0121_auto_20240521_1101.py create mode 100644 panel/migrations/0122_auto_20240523_1606.py create mode 100644 panel/migrations/0123_auto_20240525_1509.py create mode 100644 panel/migrations/0124_auto_20240528_1328.py create mode 100644 panel/migrations/0125_auto_20240605_1321.py create mode 100644 panel/migrations/0126_auto_20240605_1903.py create mode 100644 panel/migrations/0127_auto_20240606_1500.py create mode 100644 panel/migrations/0128_auto_20240609_2150.py create mode 100644 panel/migrations/0129_auto_20240612_1623.py create mode 100644 panel/migrations/0130_auto_20240620_1609.py create mode 100644 panel/migrations/0131_auto_20240622_1529.py create mode 100644 panel/migrations/0132_auto_20240623_1242.py create mode 100644 panel/migrations/0133_auto_20240626_1705.py create mode 100644 panel/migrations/0134_auto_20240629_1542.py create mode 100644 panel/migrations/0135_auto_20240630_1545.py create mode 100644 panel/migrations/0136_auto_20240701_1548.py create mode 100644 panel/migrations/0137_auto_20240702_1601.py create mode 100644 panel/migrations/0138_auto_20240703_1546.py create mode 100644 panel/migrations/0139_auto_20240706_1536.py create mode 100644 panel/migrations/0140_auto_20240707_1529.py create mode 100644 panel/migrations/0141_auto_20240713_0930.py create mode 100644 panel/migrations/0142_auto_20240713_1405.py create mode 100644 panel/migrations/0143_auto_20240713_1433.py create mode 100644 panel/migrations/0144_auto_20240713_1535.py create mode 100644 panel/migrations/0145_auto_20240720_1456.py create mode 100644 panel/migrations/0146_auto_20240724_1518.py create mode 100644 panel/migrations/0147_auto_20240725_1447.py create mode 100644 panel/migrations/0148_auto_20240727_1139.py create mode 100644 panel/migrations/0149_auto_20240803_1454.py create mode 100644 panel/migrations/0150_auto_20240804_1413.py create mode 100644 panel/migrations/0151_auto_20240805_1422.py create mode 100644 panel/migrations/0152_auto_20240807_1448.py create mode 100644 panel/migrations/0153_auto_20240808_1331.py create mode 100644 panel/migrations/0154_auto_20240810_1440.py create mode 100644 panel/migrations/0155_auto_20240813_1029.py create mode 100644 panel/migrations/0156_auto_20240819_1458.py create mode 100644 panel/migrations/0157_auto_20240820_1051.py create mode 100644 panel/migrations/0158_auto_20240821_1445.py create mode 100644 panel/migrations/0159_auto_20240826_1453.py create mode 100644 panel/migrations/0160_auto_20240829_1344.py create mode 100644 panel/migrations/0161_auto_20240831_0932.py create mode 100644 panel/migrations/0162_auto_20240912_1203.py create mode 100644 panel/migrations/0163_auto_20241014_0957.py create mode 100644 panel/migrations/0164_auto_20241016_1031.py create mode 100644 panel/migrations/0165_auto_20241016_1111.py create mode 100644 panel/migrations/0166_auto_20241017_1246.py create mode 100644 panel/migrations/0167_auto_20241022_1158.py create mode 100644 panel/migrations/0168_auto_20241022_1200.py create mode 100644 panel/migrations/0169_auto_20241023_1331.py create mode 100644 panel/migrations/0170_auto_20241024_0937.py create mode 100644 panel/migrations/0171_auto_20241026_0958.py create mode 100644 panel/migrations/0172_auto_20241026_1356.py create mode 100644 panel/migrations/0173_auto_20241031_1409.py create mode 100644 panel/migrations/0174_auto_20241103_0818.py create mode 100644 panel/migrations/0175_auto_20241103_1105.py create mode 100644 panel/migrations/0176_auto_20241103_1110.py create mode 100644 panel/migrations/0177_auto_20241103_1114.py create mode 100644 panel/migrations/0178_auto_20241103_1120.py create mode 100644 panel/migrations/0179_auto_20241109_1604.py create mode 100644 panel/migrations/0180_auto_20241109_2044.py create mode 100644 panel/migrations/0181_auto_20241109_2158.py create mode 100644 panel/migrations/0182_auto_20241109_2159.py create mode 100644 panel/migrations/0183_auto_20241109_2203.py create mode 100644 panel/migrations/0184_auto_20241109_2208.py create mode 100644 panel/migrations/0185_auto_20241110_1129.py create mode 100644 panel/migrations/0186_auto_20241110_1433.py create mode 100644 panel/migrations/0187_auto_20241110_2303.py create mode 100644 panel/migrations/0188_auto_20241112_1550.py create mode 100644 panel/migrations/0189_auto_20241116_2114.py create mode 100644 panel/migrations/0190_auto_20241117_1117.py create mode 100644 panel/migrations/0191_auto_20241117_1124.py create mode 100644 panel/migrations/0192_auto_20241119_1120.py create mode 100644 panel/migrations/0193_auto_20241120_0826.py create mode 100644 panel/migrations/0194_auto_20241126_1925.py create mode 100644 panel/migrations/0195_auto_20241126_1928.py create mode 100644 panel/migrations/0196_auto_20241127_1001.py create mode 100644 panel/migrations/0197_auto_20241201_1026.py create mode 100644 panel/migrations/0198_auto_20241203_1130.py create mode 100644 panel/migrations/0199_auto_20241203_1240.py create mode 100644 panel/migrations/0200_auto_20241204_1557.py create mode 100644 panel/migrations/0201_auto_20241208_1125.py create mode 100644 panel/migrations/0202_auto_20241208_1514.py create mode 100644 panel/migrations/0203_auto_20241209_1548.py create mode 100644 panel/migrations/0204_auto_20241211_1500.py create mode 100644 panel/migrations/0205_auto_20241214_1645.py create mode 100644 panel/migrations/0206_auto_20241216_1353.py create mode 100644 panel/migrations/0207_auto_20241218_1015.py create mode 100644 panel/migrations/0208_auto_20241218_1441.py create mode 100644 panel/migrations/0209_auto_20241222_1149.py create mode 100644 panel/migrations/0210_auto_20241225_1127.py create mode 100644 panel/migrations/0211_auto_20241225_1631.py create mode 100644 panel/migrations/0212_auto_20241231_1547.py create mode 100644 panel/migrations/0213_auto_20241231_2151.py create mode 100644 panel/migrations/0214_auto_20250107_0934.py create mode 100644 panel/migrations/0215_auto_20250107_1815.py create mode 100644 panel/migrations/0216_auto_20250112_1928.py create mode 100644 panel/migrations/0217_auto_20250113_1620.py create mode 100644 panel/migrations/0218_auto_20250120_1050.py create mode 100644 panel/migrations/0219_auto_20250201_1511.py create mode 100644 panel/migrations/0220_auto_20250205_1307.py create mode 100644 panel/migrations/0221_auto_20250209_0939.py create mode 100644 panel/migrations/0222_auto_20250209_1613.py create mode 100644 panel/migrations/0223_auto_20250210_1600.py create mode 100644 panel/migrations/0224_auto_20250211_1239.py create mode 100644 panel/migrations/0225_auto_20250212_0919.py create mode 100644 panel/migrations/0226_auto_20250212_0946.py create mode 100644 panel/migrations/0227_auto_20250212_0949.py create mode 100644 panel/migrations/0228_auto_20250212_1728.py create mode 100644 panel/migrations/0229_auto_20250212_1730.py create mode 100644 panel/migrations/0230_auto_20250216_1323.py create mode 100644 panel/migrations/0231_auto_20250222_1151.py create mode 100644 panel/migrations/0232_auto_20250223_1025.py create mode 100644 panel/migrations/0233_auto_20250223_1547.py create mode 100644 panel/migrations/0234_auto_20250224_1402.py create mode 100644 panel/migrations/0235_auto_20250224_1407.py create mode 100644 panel/migrations/0236_auto_20250224_1528.py create mode 100644 panel/migrations/0237_auto_20250225_1158.py create mode 100644 panel/migrations/0238_auto_20250226_0946.py create mode 100644 panel/migrations/0239_auto_20250303_2034.py create mode 100644 panel/migrations/0240_auto_20250303_2036.py create mode 100644 panel/migrations/0241_auto_20250304_1734.py create mode 100644 panel/migrations/0242_auto_20250307_1727.py create mode 100644 panel/migrations/0243_auto_20250317_0032.py create mode 100644 panel/migrations/0244_auto_20250414_1439.py create mode 100644 panel/migrations/0245_auto_20250420_1113.py create mode 100644 panel/migrations/0246_auto_20250430_1317.py create mode 100644 panel/migrations/0247_auto_20250503_1405.py create mode 100644 panel/migrations/0248_auto_20250504_1447.py create mode 100644 panel/migrations/0249_auto_20250505_1511.py create mode 100644 panel/migrations/0250_auto_20250506_1102.py create mode 100644 panel/migrations/0251_auto_20250510_1213.py create mode 100644 panel/migrations/0252_auto_20250511_1501.py create mode 100644 panel/migrations/0253_auto_20250517_0916.py create mode 100644 panel/migrations/0254_auto_20250518_0912.py create mode 100644 panel/migrations/0255_auto_20250518_1229.py create mode 100644 panel/migrations/0256_auto_20250520_1146.py create mode 100644 panel/migrations/0257_auto_20250526_1029.py create mode 100644 panel/migrations/0258_auto_20250527_1054.py create mode 100644 panel/migrations/0259_auto_20250527_1249.py create mode 100644 panel/migrations/0260_auto_20250528_1439.py create mode 100644 panel/migrations/0261_auto_20250531_1003.py create mode 100644 panel/migrations/0262_auto_20250531_1016.py create mode 100644 panel/migrations/0263_auto_20250531_1131.py create mode 100644 panel/migrations/0264_auto_20250531_1211.py create mode 100644 panel/migrations/0265_auto_20250531_1633.py create mode 100644 panel/migrations/0266_auto_20250601_1035.py create mode 100644 panel/migrations/0267_auto_20250603_1610.py create mode 100644 panel/migrations/0268_auto_20250607_1633.py create mode 100644 panel/migrations/0269_auto_20250610_1356.py create mode 100644 panel/migrations/0270_auto_20250628_1430.py create mode 100644 panel/migrations/0271_auto_20250628_1505.py create mode 100644 panel/migrations/0272_auto_20250707_1154.py create mode 100644 panel/migrations/0273_auto_20250708_1044.py create mode 100644 panel/migrations/0274_auto_20250708_1615.py create mode 100644 panel/migrations/0275_auto_20250709_1624.py create mode 100644 panel/migrations/0276_auto_20250713_1430.py create mode 100644 panel/migrations/0277_auto_20250714_1049.py create mode 100644 panel/migrations/0278_auto_20250714_1102.py create mode 100644 panel/migrations/0279_auto_20250719_0909.py create mode 100644 panel/migrations/0280_auto_20250719_0942.py create mode 100644 panel/migrations/0281_auto_20250721_1055.py create mode 100644 panel/migrations/0282_auto_20250722_1259.py create mode 100644 panel/migrations/0283_auto_20250723_1031.py create mode 100644 panel/migrations/0284_auto_20250727_0802.py create mode 100644 panel/migrations/0285_auto_20250729_1146.py create mode 100644 panel/migrations/0286_auto_20250803_0824.py create mode 100644 panel/migrations/0287_auto_20250805_0855.py create mode 100644 panel/migrations/0288_auto_20250806_1157.py create mode 100644 panel/migrations/0289_auto_20250807_1008.py create mode 100644 panel/migrations/0290_auto_20250809_0952.py create mode 100644 panel/migrations/0291_auto_20250809_1023.py create mode 100644 panel/migrations/0292_auto_20250809_1239.py create mode 100644 panel/migrations/0293_auto_20250809_1524.py create mode 100644 panel/migrations/0294_auto_20250810_1420.py create mode 100644 panel/migrations/0295_auto_20250817_0854.py create mode 100644 panel/migrations/0296_auto_20250817_0947.py create mode 100644 panel/migrations/0297_auto_20250817_1031.py create mode 100644 panel/migrations/0298_auto_20250817_1051.py create mode 100644 panel/migrations/0299_auto_20250817_1358.py create mode 100644 panel/migrations/0300_auto_20250818_0950.py create mode 100644 panel/migrations/0301_auto_20250820_1154.py create mode 100644 panel/migrations/0302_auto_20250825_0835.py create mode 100644 panel/migrations/0303_auto_20250825_1630.py create mode 100644 panel/migrations/0304_auto_20250826_0920.py create mode 100644 panel/migrations/0305_auto_20250826_0948.py create mode 100644 panel/migrations/0306_auto_20250827_1019.py create mode 100644 panel/migrations/0307_auto_20250827_1701.py create mode 100644 panel/migrations/0308_auto_20250829_0153.py create mode 100644 panel/migrations/0309_auto_20250830_1026.py create mode 100644 panel/migrations/0310_auto_20250831_1016.py create mode 100644 panel/migrations/0311_auto_20250901_0929.py create mode 100644 panel/migrations/0312_auto_20250901_1650.py create mode 100644 panel/migrations/0313_auto_20250902_1217.py create mode 100644 panel/migrations/0314_auto_20250902_1659.py create mode 100644 panel/migrations/0315_auto_20250907_0855.py create mode 100644 panel/migrations/0316_auto_20250914_1106.py create mode 100644 panel/migrations/0317_auto_20250914_1455.py create mode 100644 panel/migrations/0318_auto_20250915_0911.py create mode 100644 panel/migrations/0319_auto_20250915_1606.py create mode 100644 panel/migrations/0320_auto_20250916_0847.py create mode 100644 panel/migrations/0321_auto_20250916_0941.py create mode 100644 panel/migrations/0322_auto_20250916_1053.py create mode 100644 panel/migrations/0323_auto_20250916_1433.py create mode 100644 panel/migrations/0324_auto_20250920_0949.py create mode 100644 panel/migrations/0325_auto_20250920_1316.py create mode 100644 panel/migrations/0326_auto_20250922_0914.py create mode 100644 panel/migrations/0327_auto_20250922_1054.py create mode 100644 panel/migrations/0328_auto_20250922_1350.py create mode 100644 panel/migrations/0329_auto_20250924_1349.py create mode 100644 panel/migrations/0330_auto_20250924_1430.py create mode 100644 panel/migrations/0331_auto_20250925_1052.py create mode 100644 panel/migrations/0332_auto_20250925_1109.py create mode 100644 panel/migrations/0333_auto_20250925_1659.py create mode 100644 panel/migrations/0334_auto_20250927_2226.py create mode 100644 panel/migrations/0335_auto_20250929_1508.py create mode 100644 panel/migrations/0336_auto_20251001_0930.py create mode 100644 panel/migrations/0337_auto_20251001_1131.py create mode 100644 panel/migrations/0338_auto_20251004_1109.py create mode 100644 panel/migrations/0339_auto_20251005_1501.py create mode 100644 panel/migrations/0340_auto_20251006_0851.py create mode 100644 panel/migrations/0341_auto_20251006_0908.py create mode 100644 panel/migrations/0342_auto_20251006_1459.py create mode 100644 panel/migrations/0343_auto_20251007_1522.py create mode 100644 panel/migrations/0344_auto_20251007_1646.py create mode 100644 panel/migrations/0345_auto_20251008_1416.py create mode 100644 panel/migrations/0346_auto_20251012_1702.py create mode 100644 panel/migrations/0347_auto_20251021_1631.py create mode 100644 panel/migrations/0348_auto_20251022_1621.py create mode 100644 panel/migrations/0349_auto_20251025_1622.py create mode 100644 panel/migrations/0350_auto_20251026_2130.py create mode 100644 panel/migrations/0351_auto_20251027_1526.py create mode 100644 panel/migrations/0352_auto_20251028_1151.py create mode 100644 panel/migrations/0353_auto_20251028_1415.py create mode 100644 panel/migrations/0354_auto_20251029_1138.py create mode 100644 panel/migrations/0355_auto_20251029_1715.py create mode 100644 panel/migrations/0356_auto_20251102_1538.py create mode 100644 panel/migrations/0357_auto_20251102_1626.py create mode 100644 panel/migrations/0358_auto_20251102_2057.py create mode 100644 panel/migrations/0359_auto_20251102_2058.py create mode 100644 panel/migrations/0360_auto_20251103_1458.py create mode 100644 panel/migrations/0361_auto_20251103_1642.py create mode 100644 panel/migrations/0362_auto_20251104_1658.py create mode 100644 panel/migrations/0363_auto_20251105_1113.py create mode 100644 panel/migrations/0364_auto_20251109_1516.py create mode 100644 panel/migrations/0365_auto_20251110_1124.py create mode 100644 panel/migrations/0366_auto_20251111_0941.py create mode 100644 panel/migrations/0367_auto_20251111_1619.py create mode 100644 panel/migrations/0368_auto_20251115_1513.py create mode 100644 panel/migrations/0369_auto_20251116_1609.py create mode 100644 panel/migrations/0370_auto_20251125_1625.py create mode 100644 panel/migrations/0371_auto_20251130_1614.py create mode 100644 panel/migrations/0372_auto_20251202_1604.py create mode 100644 panel/migrations/0373_auto_20251203_1610.py create mode 100644 panel/migrations/0374_auto_20251208_1019.py create mode 100644 panel/migrations/0375_auto_20251213_1627.py create mode 100644 panel/migrations/0376_auto_20251214_2351.py create mode 100644 panel/migrations/0377_auto_20251215_1644.py create mode 100644 panel/migrations/0378_auto_20251216_1641.py create mode 100644 panel/migrations/0379_auto_20251217_1642.py create mode 100644 panel/migrations/0380_auto_20251221_1049.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 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/debt_report_pdf.png create mode 100644 static/assets/img/killhouse.png create mode 100644 static/assets/img/poultry.png create mode 100644 static/css/styles.css create mode 100644 static/css/styles_for_hatching_detail.css create mode 100644 templates/Digital_agreement_for_buying_and_selling.html create mode 100644 templates/base.html create mode 100644 templates/kill_house_debt_report.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 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_ticket_ticket_id.py create mode 100644 ticket/migrations/0003_messagesupport_ticketsupport.py create mode 100644 ticket/migrations/0004_auto_20241227_1534.py create mode 100644 ticket/migrations/0005_auto_20241228_1050.py create mode 100644 ticket/migrations/0006_messagesupport_ticketpermission_ticketsupport.py create mode 100644 ticket/migrations/0007_messagesupport_file.py create mode 100644 ticket/migrations/0008_auto_20250118_1751.py create mode 100644 ticket/migrations/0009_auto_20250201_1221.py create mode 100644 ticket/migrations/0010_auto_20250525_0951.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..eea628c --- /dev/null +++ b/.env.local @@ -0,0 +1,25 @@ +SECRET_KEY=django-insecure-d3)=!q#x%7%r8xu*b813f4^o*(=52#(flf@gd8psr(+=qu5an= +DEBUG=True +ALLOWED_HOSTS=habackend.rasadyaar.ir,ha.rasadyaar.ir,127.0.0.1,rasadyaar.ir,rasadyar.net,habackend.rasadyar.com ,ha.rasadyar.com,rasadyar.com, +DB_NAME=hamedan +DB_USER=postgres +DB_PASSWORD=nWYuG2dxiXxCrDz6yZKWHpyW7ExiXykb7qSAeQdPUDXBdZ17PXovrpg6KllnARSS +DB_HOST=31.7.78.133 +DB_PORT=14332 +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://habackend.rasadyaar.ir,https://ha.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://habackend.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://habackend.rasadyaar.ir,https://ha.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://habackend.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..9ced3ce --- /dev/null +++ b/.env.prod @@ -0,0 +1,22 @@ +SECRET_KEY=django-insecure-d3)=!q#x%7%r8xu*b813f4^o*(=52#(flf@gd8psr(+=qu5an= +DEBUG=True +ALLOWED_HOSTS=habackend.rasadyaar.ir,ha.rasadyaar.ir,127.0.0.1,rasadyaar.ir,rasadyar.net,habackend.rasadyar.com ,ha.rasadyar.com,rasadyar.com, +DB_NAME=hamedan +DB_USER=postgres +DB_PASSWORD=nWYuG2dxiXxCrDz6yZKWHpyW7ExiXykb7qSAeQdPUDXBdZ17PXovrpg6KllnARSS +DB_HOST=31.7.78.133 +DB_PORT=14332 +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://habackend.rasadyaar.ir,https://ha.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://habackend.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://habackend.rasadyaar.ir,https://ha.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://habackend.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..13f90b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,135 @@ +# 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 template +# 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/* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e972ad9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,59 @@ +# Dockerfile +#FROM python:3.9-slim-bookworm +#FROM ghcr.io/seniorkian/python39-rasadyar:1.0.2 +FROM registry-ea28d41763-mnpc.apps.ir-central1.arvancaas.ir/python39-rasadyar:1.0.2 +ENV TZ="Asia/Tehran" +#RUN ls /usr/share/zoneinfo && \ +# cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && \ +# echo "Asia/Tehran" > /etc/timezone && \ +# dpkg-reconfigure -f noninteractive tzdata +# Set working directory +WORKDIR /app + +# ساخت sources.list جدید با mirror ArvanCloud (برای سرعت در ایران) +#RUN echo "deb http://mirror.arvancloud.ir/debian bookworm main" > /etc/apt/sources.list \ +# && echo "deb-src http://mirror.arvancloud.ir/debian bookworm main" >> /etc/apt/sources.list \ +# && echo "deb https://mirror.arvancloud.ir/debian-security bookworm-security main" >> /etc/apt/sources.list \ +# && echo "deb-src https://mirror.arvancloud.ir/debian-security bookworm-security main" >> /etc/apt/sources.list \ +# && echo "deb http://mirror.arvancloud.ir/debian bookworm-updates main" >> /etc/apt/sources.list \ +# && echo "deb-src http://mirror.arvancloud.ir/debian bookworm-updates main" >> /etc/apt/sources.list + +# Update + Install system deps (with apt cache) +#RUN apt-get update && apt-get install -y --no-install-recommends \ +# build-essential \ +# libpq-dev \ +# python3-dev \ +# libcairo2 \ +# libcairo2-dev \ +# libpango-1.0-0 \ +# libpangoft2-1.0-0 \ +# libpangocairo-1.0-0 \ +# libpango1.0-dev \ +# libgdk-pixbuf-2.0-0 \ +# libffi-dev \ +# libjpeg-dev \ +# libpng-dev \ +# libfreetype6 \ +# libharfbuzz0b \ +# shared-mime-info \ +# fonts-dejavu \ +# curl \ +# && apt-get clean \ +# && rm -rf /var/lib/apt/lists/* + +# Upgrade pip +#RUN pip install --upgrade pip + +# فقط کپی requirements و نصب پکیج‌های پایتون +COPY ./requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy project files +COPY . . + +# Expose Django port +EXPOSE 8000 + +# Run Django development server +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] +#CMD ["gunicorn", "TestChicken.wsgi:application", "--bind", "0.0.0.0:8000"] diff --git a/GateWay.py b/GateWay.py new file mode 100644 index 0000000..bd12e57 --- /dev/null +++ b/GateWay.py @@ -0,0 +1,74 @@ +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/HaChickenStore/__init__.py b/HaChickenStore/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/HaChickenStore/asgi.py b/HaChickenStore/asgi.py new file mode 100644 index 0000000..37737be --- /dev/null +++ b/HaChickenStore/asgi.py @@ -0,0 +1,14 @@ +""" +ASGI config for HaChickenStore 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/3.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'HaChickenStore.settings') + +application = get_asgi_application() \ No newline at end of file diff --git a/HaChickenStore/settings.py b/HaChickenStore/settings.py new file mode 100644 index 0000000..81554da --- /dev/null +++ b/HaChickenStore/settings.py @@ -0,0 +1,262 @@ +""" +Django settings for HaChickenStore project. + +Generated by 'django-admin startproject' using Django 3.2.8. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.2/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(',') + + + + +# Application definition + +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', + + # 'rest_framework.authtoken', + +] + +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 = 'HaChickenStore.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 = 'HaChickenStore.wsgi.application' + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases + +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"), + } + +} + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', + # 'rest_framework.authentication.TokenAuthentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ), + 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'] +} + +OAUTH2_PROVIDER = { + # other OAUTH2 settings + 'REFRESH_TOKEN_EXPIRE_SECONDS': 360000, + 'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore', + 'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}, + 'ACCESS_TOKEN_EXPIRE_SECONDS': 360000 +} + +AUTHENTICATION_BACKENDS = [ + 'oauth2_provider.backends.OAuth2Backend', + # Uncomment following if you want to access the admin + 'django.contrib.auth.backends.ModelBackend', +] + +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0", + # "LOCATION": "redis://127.0.0.1:6379/1", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + # "PASSWORD": "foobar" + }, + "KEY_PREFIX": "You have successfully set up a key-value pair!" + } +} + +# Password validation +# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators + +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', + }, +] + +# Internationalization +# https://docs.djangoproject.com/en/3.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +# TIME_ZONE = 'UTC' +TIME_ZONE = 'Asia/Tehran' + +USE_I18N = True + +USE_L10N = False + +USE_TZ = False + +DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' + +# Cache time to live is 2 minutes. +CACHE_TTL = 60 * 2 +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.2/howto/static-files/ + +STATIC_URL = '/static/' +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static'), +] + +# در حالت production +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') + +# Default primary key field type +# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +DATA_UPLOAD_MAX_MEMORY_SIZE = 50242880 + +# CELERY STUFF +BROKER_URL = 'redis://localhost:6379' +CELERY_RESULT_BACKEND = 'redis://localhost:6379' +CELERY_ACCEPT_CONTENT = ['application/json'] +CELERY_TASK_SERIALIZER = 'json' +CELERY_RESULT_SERIALIZER = 'json' +CELERY_TIMEZONE = 'Asia/Tehran' + +if DEBUG: + MIDDLEWARE += [ + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ] + INSTALLED_APPS += [ + 'debug_toolbar', + # 'oauth2_provider', + # 'rest_framework', + # 'corsheaders' + ] + INTERNAL_IPS = [ + # ... + "82.115.17.44", + # "127.0.0.1", + + # ... + ] + + 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', + ] + + # this is the main reason for not showing up the toolbar + 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/HaChickenStore/urls.py b/HaChickenStore/urls.py new file mode 100644 index 0000000..67c900e --- /dev/null +++ b/HaChickenStore/urls.py @@ -0,0 +1,29 @@ +"""HaChickenStore URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.2/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 + +# Mojtaba Zolfaghari Development +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/HaChickenStore/wsgi.py b/HaChickenStore/wsgi.py new file mode 100644 index 0000000..4983c04 --- /dev/null +++ b/HaChickenStore/wsgi.py @@ -0,0 +1,14 @@ +""" +WSGI config for HaChickenStore 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/3.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'HaChickenStore.settings') + +application = get_wsgi_application() diff --git a/Herds.xlsx b/Herds.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..baca871cc61ad8c5e05d30c2eeaae613211a29bf GIT binary patch literal 85055 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 NmpGMFcnM*+{{l@{N@oB7 literal 0 HcmV?d00001 diff --git a/Herds2.xlsx b/Herds2.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..769c62b8514b9f82a9345836d245a7b52fcfde3b GIT binary patch literal 84468 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 z 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 Keu@60*Z&Veh6Y3c literal 0 HcmV?d00001 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..dd9d0bf --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/helpers.py @@ -0,0 +1,19 @@ +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) + for _i in rancher(110): + pass \ No newline at end of file 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..b35486a --- /dev/null +++ b/LiveStock/Rancher/excel_processing.py @@ -0,0 +1,608 @@ +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 + +def create_live_stovk(request): + l=0 + for _i in range(60): + live_stock=LiveStock( + national_id_livestock_code=random.randint(10**9, 10**10 - 1), + herd_code='000005307', + type='اسب', + birth_day='1402/12/27', + birth_day_gh=datetime.datetime.now() - datetime.timedelta(days=360), + gender='نر', + unique_identifier='0000053070', + ) + live_stock.save() + l+=1 + return HttpResponse(l) \ 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..27c6ae3 --- /dev/null +++ b/LiveStock/Rancher/helpers.py @@ -0,0 +1,110 @@ +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): + 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..911f867 --- /dev/null +++ b/LiveStock/Rancher/urls.py @@ -0,0 +1,40 @@ +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, \ + create_live_stovk +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), + path('create_live_stovk/', create_live_stovk), + +] \ 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..ff46171 --- /dev/null +++ b/LiveStock/helpers.py @@ -0,0 +1,19 @@ +import jdatetime +from rest_framework.pagination import PageNumberPagination + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +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..3f9d532 --- /dev/null +++ b/LiveStock/migrations/0001_initial.py @@ -0,0 +1,187 @@ +# Generated by Django 3.2.13 on 2025-03-03 20:36 + +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 = [ + ('authentication', '0050_auto_20250303_2036'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + 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')), + ], + options={ + 'abstract': False, + }, + ), + 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='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)), + ('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='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')), + ], + options={ + 'abstract': False, + }, + ), + 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')), + ], + 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)), + ('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)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_address', to='authentication.systemaddress')), + ('cooperative', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_cooperative', to='LiveStock.cooperative')), + ('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')), + ], + 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.livestockprovincejahad')), + ('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')), + ('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)), + ('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)), + ('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.livestockprovincejahad')), + ('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')), + ('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/0002_livestock.py b/LiveStock/migrations/0002_livestock.py new file mode 100644 index 0000000..1898a15 --- /dev/null +++ b/LiveStock/migrations/0002_livestock.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.13 on 2025-03-04 13:40 + +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', '0001_initial'), + ] + + 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/0003_auto_20250305_1353.py b/LiveStock/migrations/0003_auto_20250305_1353.py new file mode 100644 index 0000000..8c1972e --- /dev/null +++ b/LiveStock/migrations/0003_auto_20250305_1353.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-05 13:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0002_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/0004_auto_20250305_1721.py b/LiveStock/migrations/0004_auto_20250305_1721.py new file mode 100644 index 0000000..af6b71b --- /dev/null +++ b/LiveStock/migrations/0004_auto_20250305_1721.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.13 on 2025-03-05 17:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0003_auto_20250305_1353'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='allow_buy', + field=models.BooleanField(default=True), + ), + 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/0005_auto_20250305_2028.py b/LiveStock/migrations/0005_auto_20250305_2028.py new file mode 100644 index 0000000..9daca3a --- /dev/null +++ b/LiveStock/migrations/0005_auto_20250305_2028.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2025-03-05 20:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0004_auto_20250305_1721'), + ] + + 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='weight_quota_heavy', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='weight_quota_light', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0006_auto_20250306_0023.py b/LiveStock/migrations/0006_auto_20250306_0023.py new file mode 100644 index 0000000..3e067cd --- /dev/null +++ b/LiveStock/migrations/0006_auto_20250306_0023.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-06 00:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0005_auto_20250305_2028'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='total_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='livestockrolseproduct', + name='total_remain_weight', + field=models.BigIntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0007_auto_20250306_1213.py b/LiveStock/migrations/0007_auto_20250306_1213.py new file mode 100644 index 0000000..1c4d792 --- /dev/null +++ b/LiveStock/migrations/0007_auto_20250306_1213.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2025-03-06 12:13 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0051_auto_20250306_1213'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('LiveStock', '0006_auto_20250306_0023'), + ] + + 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/0008_auto_20250307_0930.py b/LiveStock/migrations/0008_auto_20250307_0930.py new file mode 100644 index 0000000..162f852 --- /dev/null +++ b/LiveStock/migrations/0008_auto_20250307_0930.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-07 09:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0007_auto_20250306_1213'), + ] + + 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/0009_auto_20250307_1059.py b/LiveStock/migrations/0009_auto_20250307_1059.py new file mode 100644 index 0000000..0412c43 --- /dev/null +++ b/LiveStock/migrations/0009_auto_20250307_1059.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.13 on 2025-03-07 10:59 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0008_auto_20250307_0930'), + ] + + operations = [ + migrations.RemoveField( + model_name='rancher', + name='address', + ), + migrations.RemoveField( + model_name='rancher', + name='cooperative', + ), + migrations.RemoveField( + model_name='rancher', + name='user_bank_info', + ), + ] diff --git a/LiveStock/migrations/0010_auto_20250307_1107.py b/LiveStock/migrations/0010_auto_20250307_1107.py new file mode 100644 index 0000000..2b7ac6a --- /dev/null +++ b/LiveStock/migrations/0010_auto_20250307_1107.py @@ -0,0 +1,48 @@ +# Generated by Django 3.2.13 on 2025-03-07 11:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0009_auto_20250307_1059'), + ] + + operations = [ + 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/0011_auto_20250307_1322.py b/LiveStock/migrations/0011_auto_20250307_1322.py new file mode 100644 index 0000000..691ca5b --- /dev/null +++ b/LiveStock/migrations/0011_auto_20250307_1322.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-07 13:22 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0010_auto_20250307_1107'), + ] + + 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), + ), + migrations.AddField( + model_name='rancher', + name='has_script', + field=models.BooleanField(default=False), + ), + ] diff --git a/LiveStock/migrations/0012_auto_20250307_2135.py b/LiveStock/migrations/0012_auto_20250307_2135.py new file mode 100644 index 0000000..5277e0b --- /dev/null +++ b/LiveStock/migrations/0012_auto_20250307_2135.py @@ -0,0 +1,47 @@ +# Generated by Django 3.2.13 on 2025-03-07 21:35 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0011_auto_20250307_1322'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockproduct', + name='cooperative_percent', + ), + migrations.RemoveField( + model_name='livestockproduct', + name='union_percent', + ), + 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), + ), + 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/0013_auto_20250308_1617.py b/LiveStock/migrations/0013_auto_20250308_1617.py new file mode 100644 index 0000000..5467012 --- /dev/null +++ b/LiveStock/migrations/0013_auto_20250308_1617.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-08 16:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0012_auto_20250307_2135'), + ] + + operations = [ + 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/0014_auto_20250309_1654.py b/LiveStock/migrations/0014_auto_20250309_1654.py new file mode 100644 index 0000000..52f3d71 --- /dev/null +++ b/LiveStock/migrations/0014_auto_20250309_1654.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-03-09 16:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0013_auto_20250308_1617'), + ] + + operations = [ + migrations.AddField( + model_name='cooperative', + name='active', + field=models.BooleanField(default=True), + ), + 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), + ), + migrations.AddField( + model_name='livestockrolseproduct', + name='total_receipt_weight', + field=models.BigIntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0015_auto_20250310_1820.py b/LiveStock/migrations/0015_auto_20250310_1820.py new file mode 100644 index 0000000..3c2d4c4 --- /dev/null +++ b/LiveStock/migrations/0015_auto_20250310_1820.py @@ -0,0 +1,58 @@ +# Generated by Django 3.2.13 on 2025-03-10 18:20 + +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', '0014_auto_20250309_1654'), + ] + + 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), + ), + 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), + ), + 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/0016_auto_20250311_1055.py b/LiveStock/migrations/0016_auto_20250311_1055.py new file mode 100644 index 0000000..ac5a2fc --- /dev/null +++ b/LiveStock/migrations/0016_auto_20250311_1055.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-11 10:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0015_auto_20250310_1820'), + ] + + 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/0017_posseller.py b/LiveStock/migrations/0017_posseller.py new file mode 100644 index 0000000..fd04d34 --- /dev/null +++ b/LiveStock/migrations/0017_posseller.py @@ -0,0 +1,37 @@ +# Generated by Django 3.2.13 on 2025-03-11 13:36 + +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', '0016_auto_20250311_1055'), + ] + + 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/0018_rancher_type.py b/LiveStock/migrations/0018_rancher_type.py new file mode 100644 index 0000000..3ea9d47 --- /dev/null +++ b/LiveStock/migrations/0018_rancher_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-12 11:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0017_posseller'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='type', + field=models.CharField(default='rural', max_length=200), + ), + ] diff --git a/LiveStock/migrations/0019_auto_20250312_1429.py b/LiveStock/migrations/0019_auto_20250312_1429.py new file mode 100644 index 0000000..0f03157 --- /dev/null +++ b/LiveStock/migrations/0019_auto_20250312_1429.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-03-12 14:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0018_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/0020_auto_20250312_1459.py b/LiveStock/migrations/0020_auto_20250312_1459.py new file mode 100644 index 0000000..d722f7d --- /dev/null +++ b/LiveStock/migrations/0020_auto_20250312_1459.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-12 14:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0019_auto_20250312_1429'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='dhi_amount', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='industrial', + field=models.BooleanField(default=False), + ), + ] diff --git a/LiveStock/migrations/0021_auto_20250412_1613.py b/LiveStock/migrations/0021_auto_20250412_1613.py new file mode 100644 index 0000000..ddf65eb --- /dev/null +++ b/LiveStock/migrations/0021_auto_20250412_1613.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-04-12 16:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0020_auto_20250312_1459'), + ] + + 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/0022_auto_20250528_1439.py b/LiveStock/migrations/0022_auto_20250528_1439.py new file mode 100644 index 0000000..4ee6f5e --- /dev/null +++ b/LiveStock/migrations/0022_auto_20250528_1439.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2025-05-28 14:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0021_auto_20250412_1613'), + ] + + operations = [ + migrations.AddField( + model_name='cooperativeproductsshare', + name='company_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestock', + name='age_of_archive', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='livestock', + name='archive_date', + field=models.DateTimeField(null=True), + ), + 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/0023_auto_20250810_1134.py b/LiveStock/migrations/0023_auto_20250810_1134.py new file mode 100644 index 0000000..91dac23 --- /dev/null +++ b/LiveStock/migrations/0023_auto_20250810_1134.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-08-10 11:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0022_auto_20250528_1439'), + ] + + 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..1cac4f7 --- /dev/null +++ b/LiveStock/sms_management.py @@ -0,0 +1,31 @@ +import requests +from django.http import HttpResponse + +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) + + return HttpResponse('pk') \ No newline at end of file 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..2673f47 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# ChickenStore \ No newline at end of file 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..cc315d0 --- /dev/null +++ b/RasadyaarBale/helper.py @@ -0,0 +1 @@ +Token="1092215072:Dg6DpySANPbpARwBRzftJzmMLKBRiFS7yIoXsTig" diff --git a/RasadyaarBale/migrations/0001_initial.py b/RasadyaarBale/migrations/0001_initial.py new file mode 100644 index 0000000..510d1ca --- /dev/null +++ b/RasadyaarBale/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-27 10:54 + +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)), + ('super_admin', models.BooleanField(default=False)), + ('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_rasadyar_user.py b/RasadyaarBale/migrations/0002_user_bale_rasadyar_user.py new file mode 100644 index 0000000..a7e9e33 --- /dev/null +++ b/RasadyaarBale/migrations/0002_user_bale_rasadyar_user.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.13 on 2025-05-27 12:02 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0053_auto_20250527_1202'), + ('RasadyaarBale', '0001_initial'), + ] + + 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/Users.xlsx b/Users.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..23eb826b1a3a1bec8cb0ab805b5f18cbdab4beff GIT binary patch literal 92233 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

qB3R!Jjh2=!2QSEC&kz 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 x-zCTqB>*4`0|Ne2kdVUvoi%=k1=#=q literal 0 HcmV?d00001 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

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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

)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 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 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/debt_report_pdf.png b/static/assets/img/debt_report_pdf.png new file mode 100644 index 0000000000000000000000000000000000000000..5f54b68bd1a2a864d823326798dfb2983d1bfc34 GIT binary patch literal 2033586 zcmeFZcTiL7*Dr24>Jh|tC`wfU=^)a(pn!n%5&|Je3xq0Nx(!q!ptR7D5=ugmP9OvY zLrX#+)X=2_fzV5+dUNi5-*Yqt@v-N+QW>U^Np0tpHDmM@GYC&=}p^(^2WHa5Y z7jsm{(jymO9(MqqMl~Rpmz{&IzM%6)rvK;r2~WdSF|B$nyFsn0>VVO5Vnd2PF~fx1 zJgosvHk)BKN%y5SVE$#4Wu0cdB2iD=}kX@ zq;^WayGuvoO+a+X5ojmg{41mkKy>!a7yQha_QzGCS=C0gsjED;w< z7yGWc-?;xoPAyE#-rNT)2YHS?b-WltBoeFs^KE~~ZM9BYxTWN;-ND|DeM*Y1Xde*Dq_cuZ-V{AY$*WK%idG6FqUEEHFbm&<*)Em#{x zd0-P*?tZjmZrJ*5iz^gazy4sCS6XNC{1reTNgcUDG0?QEJLReThV-AGVEaaKH%y*N`~9egNyvg%?mJ1-k~{Q*9H{goRe9iZ$0V*28u zS>HITn0KP0KkI3Aqj-^?sA$98A)28Sd&k}sYs2z721QTfu~c|2vwO2HE;M0O-;!nW zkD1Ab`Uk2Pd&qr2D{--CV)ear;CiuvgoanC z$T-Q%j`!`+UxGjC3Vqq(cie$A0)E!h_W)3rS-=4wl06Yh~oVr^B*7S)Rb%6o>h645|H_> zdgVfr{Rk(Ql7|iAmSoozjDR1zuH=2{uje^u1S6y~nPKEPf!j6C?+tLSt({-{hAXgTT^eiM~qi|rO1MtaE z#7+>BSN6%-1}@ZT+try0wy)#-;eUgne|~)p19GEAhx09KirjVy3U$s~2JTrZhCC>^ zLG-Y|lT_9g*3swb5y28Qqqwj6W`7XGKiuJ9f|1+O7j>aqV)dEL!qz`8Al-i!g)?$u zX~`Ljw+E;DH&v<%|1!WljL9 z02PMZ@=&H;I64p`KN zJWzInVJMyi@$H212~YF6i^F3$b@5qsV;c6N>)v= zb@M4vql9a&i^dAO1G|w+v`?8yB?Wd~M32Gx&=ebhxY+VI!u3Dy8*i!ED@nc26x5XFQiXwX2n+T3*1p#F#&s$#40{JL zpJ0|Ru$bpcGyq7ZDkY?n)uG_;R!mLw)QPF8@!|8`iHblFG7;?p6e+s{rlx2)E`UCb z%iGPO?^!D;rg~@}X0QW>AE5 zYQ77EcQzKaN!}K?SZA_|f>$*mDJbE z%gHyCK)niv%fRI+9#$T^V|6wye$kx7YBrByx3~~FxpGSb^Q5t{@u7(c&#Cdjso{z} zElr;2%WSYbmDkM0>2Q{Jlr-zWz`D>KT7~+_VW}%A2U+Q3Lh_y*s?jyxUe4of2}MS& zt1l1Lz(WJpi@=bOhj!WHQeX0_#FtaSy6k2K71Bm$p(z|7->3;1oLE$o;ed&-kD;s8 zt>;$*zl2_y(y|QPJ){2f-n&=O1*R_$=+mqc_9`vio^QVd$a2@ zC4X-Um(rgD%3H9bSpm+eH!p)4 zoAEI=c3Ag~lsEmNuN^69Ol^~udU21bTyTW1nN`jBAy~PrmX{g^Ehb2vBh1pm{7yCK z8Cu3IySopzV8LfY=|eA0pU6Gyd&(le{!pF^Nql>$|JHWI)AcDNs$A}9^eS-vjz z7YKdkyR`0U=~;P5NC9En&Z!3VpB)}g*QON`t z#~*9z9Z*Y&dO8L4@GTsGoi^E>i1cCMJ-W8bgD&41k~^dR?q65>;v=5&47DH95}|vV zazx&Y!{SU_-Z-?@(Py4nVhZ^s9rzYy@9W4x5x;Rk3&jay!7 zC8%In>+QIZU-3Iu?Yu-YfZy@_lkQ-y?P|eF@mr}NfM11~6%lougBYG~b3#bFO3PBx z(sR85*m_0LY{lj*avJRn=}O{^?F|G9LzX5wE)Wh6n>bl$1IGL@ECa)~@%`Q^>-k+yNU<6SWwFYgywd-(UA-tK@-=?(y!xqsTiy-H z_wD(qnB5F^)$PyhEgL2I9WGm*Z3LYP&pY_&Zy?Sx?%%OYkcjI8qG=~5P2QZ11M15) z+rK!QRv5TL;ZYTbMGkHk3%c}V!355nAo4zdV!1bDD*lrQ9gy|i5+G)&nfn-KSBMN0 zd#qv5dW~Wm7Voqga$(mf8>uK?5tdZ#rQq$gEzc#90nc=pAKE_?1X`z$5VmC zttuIVtV9i@^6Nlh#2EMS@`mBdP(TJqU^FrQPTG!S()Q}-1L)GijCdwFNt-}t54yYZ3p^ZLQxa>T4Mx7=@_vk%uI z({#e;O)N*~S2rSc|E+LEJ>-sNz&ktUoG1(C+%Rh*^J3#@I^SrcrSP;>WWK<{f)?OY zTvW6-*EqI1ce&w40aj(T_(vFD(G-6}BES+}izyS|Pl*iPloZ^Q2)5Yvu5p%kmiOui zQ2RX#%h;mYW^8QXGq#3p-LI$+lxQLC&U_rE23k*{JOl~)nd$6-hRqtq_dbF=bpmGW zZ%spg6*@tJ_v~l}dT+$z(3F>rU1=fo2o0X%9$y)fq3$9~)D8&Ge-aUb#@ui^~p>XdbRtHwHy`UAuFui(+X4;xfx^(4X&mh&sq z>Pe*Ls$txgX9odhca=cJvA(S!EaW?w&L>)(vlZS(thG0gU)b#pe6G5H9O?2(sa#Ke zR7>8myncv$@&``x5<5=M28Ad$l!5dPawQ3Qv@uJ$%_b|zISoH42aXqx(k(t{aY(~j z1imkfzDr+3=;}MUfUk3jwH!q%sZ;eq)KE~7M97uNdQmxi^_+ljwclw1>i8-^e7o8j z=tt{m%j7|+1lrt%FD|{jO&Pb2E|NK zLh@wwm0SHg$a=OCB*Lym=gPEJvv)(w-b6&OR|7F<%za0A$YLQWqB_Ks9f7BI`#UId zgoy=|K-Xj?LVxht{MxFqQSqGb@vmD_*9VjhMD7_ZFPu9`m7Z zCL*5vMeT}3MDEKoQ^xo?N zJNJs&n$5FIv{xh-HNcB<21}wGXE$<-gL#@pnvKHqsG^ zkcp@Q_SUTr`Sm*IUP?{Vll^^>h0uljmJV)s8>YEe%K0Xdq|=;1eR`b!qnpd>&V`g) zQkgn6B4xGyR_sFf{I0UNJ8}*6OV|r*BTmK|1;s+DD4bX-%59Iiy=$R0Tqed(g$Sak?izph?#PH(^snnpZcL}=DkIGN(k=_0ml4PNnx^Uj`MdgBy7boyuw6|pz*aCgXZYrxu8J~9m3Wxiyy zdfee)S`LGFd`pTN%HK>V`SL91rc*!nl<}D$%^Asd?G228rEBMnu^GFM@R2D0IQ6wl zUiB-w$(0q?Ho*T%HCTRHH|xXfL(Tkon{CBhF?o#zI9$t?{BuG0)g)p7`X_)J{S3&; zW;s;ed>F6x$d)@a@z7JviV3N|S)nNMDrI^VTOCm`Dv`P0A#k$#?d|TyT*A_Bw@=B_ z_?u&a@~;*$o%X?F=eCn>0F$)|aishr_2_+bhjfzJsyJ}!=>XYYBcnlWB z7SAyqKQNUn?wZOJ*00plQzV{jrf@Z)&(i|m$d9kw3tZQD{56c_--IDiT-BJB)Ih!~ z-yq?FkJa{8^cHKArThbzkqhAK$~8+OTo|T;{9~l(?s!nJm+!tF=a-|~kh$}Mma?q@ z6Fm>$aUg~=6|bdfJ{4{re6m~Fw9u%73k=JMJq2bL`uEhlv`o5E92!m7Nz8fJa@ zb%cMDZG~F!bvr2`Z{6+eDhc| zx~u1#Or`39w-KhdpPniWSxtQ&JZbwGoq^ z8wBki)gQAtnw{Qy8?6S{sKy%j)?*?dv3Wt0z8u-l2c?yNjTXoTbX{F|H9uB^hE;p$ zwR`OSdh2CqqrRy`44bi%GYU1;wDqq}2pMh*@V4707*NUa-vSq#b}e(O-ntJ;=UP0> zJ$+_M?BBNOTj)m1l`UhYHx&fg!VvSc2vIwYU( zn%|>?MtcnIxJrgY+HIl2gp}$#@PjS#RU7TIgmbN);rPnOG3cu{Svu8(;OQ&mZ-Sqy zJ%KJGS4tUONhj)xlu^sW^cH+Yl&maFt;MwaX2~IHt*RFhGnt7Sz-q)zbJo=O zZ0#w>;OTIcA4sMxWO+sZ=xQ+8SC_lA{fd&w!wXj|KJv(*57yF5OP%4|4S_#YC5}5= zY?OaotCLDgpO98*MT3^cY8Z00b>7pQ-ovTo=9QP6zJnsmbrklouRP~}IsMzps}JTo zHghgM8KAXJ=OHRp5!4hI+de~pe(y$kkroF)&j1DNwHZp8+|!2FvitnH9$zmX^;A~i z4{h~6B3ZHeznI!hJTfzOcWOvKr;gSY)=BQa$bzDy`BuFE=Q$gy0M;N}uwP~bqmQzc z^jyF#RR^Gd6gyNFeoFb{TexLRi)w@F#gtMX!0C_(7&wk_OM0l=R07f5;(BtDU)w7Xqvgm0}0xI@dTSl^K|_!(81c!xPqX zB=lR*L0;jfUxI{Eu9|o95V=QME_l*6^tUMW&WRZ|NNNR_UgeTk9Z=Z?4huaVr6<`j z($5(-;8AtE_A3TSsCNn;)1Hf0(s|1h@FnIlPkuOD5t!Wj)K5b-I{I??b1w|_cvs41 zn`#iNGM30xw|{fF4McRRGrQt_*HG>@1z`Dt~l}<+sGYxdD7ezGZU$Q-eE4 zKErJn6H59pHj%x6nZ^0>k`$s2PA|XneEAtRhILX(+*8rvzpQS$%O7Myn{|Vh;c->u zhq`)9s2ee%5wil5^smza0d z4>@mq*OyZkpKlkbZP-OmazYK#w^+3)*Jfp7Q~&72-1^v75}+>i*bxYpWC^BdI3x}v z!q4MG+kipG-V-m^&-iqE?n9X+Bw*>2{2a#H`k(4Y#dJqOe-Md!_iYf{Yf~oz`wQc9 z#n+mITlVfT8Dxqy+xxOBz~)Qucoqq;!np^GsZwz$5y{RrjO<Id@llhjj_7JOZd@zu%B-+KE&2$ObL$)xc%!d4VQOsz2Ti28YZ;rX6pf_yMSw&3uKX zx)C6?7$1={Zu`dnhHCboy>}|l*ezm!n%95R(0oVO@vX%+Go@+&_tMib_}P2!;prqb z9iK|+x4C6`7jlFvkrk}@)jv=bosv4AsD#YQ@wG;Cg{jaaNN;X&ew-ae*y?KI11qb? z%$Qpji%PjQ%tgK;cDSK#gkNwSOmYkS6%;%s$XHY<60SedY4irbs zF^oi@fpH$gC8ec6F{`q^F>28~Co$`AX`*Q+lTYBJRyZBjb&gVvmYLgoz0)+WWH}G|D|MB96Zk^$L*<0|{8Q0r&vdSD{EdcQS5rlt;UYf)czmC3^n;kVD@_?29aa?@$U-}@z6~BKPCS+GM{5o`%2&LW@ zarf_+A|10mugFFyUK&ue5}poUS9cHd3L|q2`82e%9=xQ;8)?}>BSn?GY5CTuVcBIg zhy5Ta^1#34{-zw8lW`tL`q@R#YxpdDaPvMi86Q(|Ec?;r_tt=7$`MttGcZtWyZQ)n zyQ0vAir{}|Hz7uu;BNPH?Q|SDk~Bya=u5N)(CXh$(zilrUpxm1s7uInbkCw65{0s? zseVZXCJm6Mx;ohQsmz3Vyh=RKzeiA(Y(%B0k@3 z?}jODO_SACS3e>5JZV1LJ^2D=(?13-p^yk{AoKCEQbm~dntH6N$F9q9^JzxV5 zGO`uIrn(Z?igceXN|PL}9!Y*^80wM;oPuLZ9$p@`KMAG#k=*6AefP>5pXChplM9s+ zCQ%J*O;*2pqSwYSSuCFqmKx7AM9@0^%2<>s{&f^#;bf%vu&(8Zd35k!E7$1kRSPU)82eIw7YGE{*m)S zmL)5WQMY`a0dzdXva6~A5_~Xm7 za*q4Y;&|0;GJVuR401N~`Q_Qc7Te&Vks*;UKkfyyAdu;pxIw%q0Jm~rG1Y;3obFOp zyJLo_=oI(KEH}_{1n=F3;t;Pre5BlP%PBUs&)-9Ovr0<`ilNAmTy>`yb_rnqP+VL+ z{jOB5F|~V2NJaxV+A9{_liV>+Mw8C}Jm`Km!QF|#AX^1{Nb2eds{cW7NVFLJ!JX@RV-?q_94Y zE};EOIqQWX$s4KEQt}jlmT%?2x>V7;-p|r7Q7Dv~`B{q_+0Lyid6iw@b}tzyRVo@*)y^qUjCByi}CcC}&kgO_n{(1YfM!k6qW z;Ul>kSHNRSgFeW}Z7;hUJucPy5uzjPvi{rtXu-<4Hs}h6g`;vwHua(z&QjJo}{Xa=Gz;YiE^>5!d*5-oxYkpBYa2nw# z5SUMmX{4dU=(JM1;3@6qv=MpRxPD%zPNZ?JI#Z$}eEcpNYR_GV(0C5y|BET18G`AA4rr6S;_fEWGbP)CKGmdT1SF=_T zX!a*8L){~_$SAW24vsLCG7h&(x@$~EcIebN%&Z|ipAvNX$xa>An_Hk{Nzu6C`@AC| zh23)6OD%B&U+jc{4~XVVQ+J&{kX_}J@_jl!CPb`O6N3)h(p{JK3*s%j4C}&*k~=7l z{)t@%y_Eh&kU>t^GHB2z}5>dGM{28C6J#X%AC9Un_kq;Akw%j4H=e=5+Z}Oj( z#f1IWrm239Dg`d8!O{&3Gt|c;g#OX*|N7Rr%B8$WBOsIdd(OK~B6Cs8NOJ}seEYub zb0)hoQ8Qtw5;Ek7uXI)Ym&?#4&b-lcId?1v8(7hwQ;NF>ru?dER(!B}9vK-H?_%}D zduVfxt`t70_wkgmWcz+uyqPWHPn)JYFvk?5^!gTzpS0M;OoXpQLw4?Y3?XnI8jgpc z>L)|RR$Gp87^-Y`;LPa@CAo1~=~V}8yZ5-JuakNE_bBD%fe}nvyP$kqRTBMR#!z?nMK)QOhhr!jH9d3Yfa%Y z37YCYMKUH+n33VZlDvAI-MU?Ow-SJt-Rq_yg%SWMXL+O{p^5%8Pn09mKxa9OvY+U& z#R`}onvHE0Thn$)6tA#e$3brqRgE1?2Z{_w<{PHS?Z2N}NMW{OVFd>VqQSo>Q2_H+NiVwC-QM`+Eu3AJUGis~F8W$hLmT!UvfzJj}Y*li984j^bTlqe1U>az$pxtpY zbp}%-W;1=36GncUHcW&RXN=q0J?P;c#e{RP8MImHZHRlAr#OQ29|9cM|AYY*HHd$h$dRYYhi^Pxt!+0N`^|r}^o~E?Bv-v9NgCIE5U#&=(C^>VSr+6;}BEQkTzH_5n+hG(BrC4q%#W)3$>^+HC& z(;TX#b>WZ)m))Rv{SO7M*E0SYJW{DW*BWFWQ;jlnMB)cntwEg8`e$QP?k>=RAiS}8 zV&w}cm6$9 z)T&W2E&0|q$X5JjF5G!J)}e$^nU{WD;2Yd$Z0BM=m^_Bv+$BRwo|M11fcT*-1LkNo zSR9O>j#Bz`bJQ0bs7O z;lm3o_eibqDeCBCrf>_jB(NN!@eD@Qc-E|(Dq-?*ds2ocb5T^^*n9iM+J0b!?0jF6 z?BTlvM(2^#%(UkJaep?j!7Hzgf98u-nmd^r6fe9X$MLMI=ptX;^R{Us{S|{9u50Vfi(a)?u1`iL(Ef7c7|$Kg zzyX^;)>z0BKYy;~=Qi^lfY{V@wBB8^6rdS2gI~X{xN@BXpXiDBCg`93s0|a~tJFbl zvj^V~_Dy!iOn?9uZ4*5Ao$%>LlQnsnhr7#&YwZdnsRg>3BdKGML17jy`6p)&_as)S z@O5huNou+4^*Qkm@Cw^1zvv>&ZV_+TmYy0kCuQVrOWtt(A+M&eJ+T;fNkjFlCY>BX5Lh8LB)=QZICOa2^G(?SNO-;*62V8%)@!6Mk=0@sB zLS;^|Tm!-e(g6Kgjy;17 zI~|4ZLr>z~bN-(2&rpiW8LqESLyI;w+S0Tkmmo*?WdFKZ=ww`3GQr`$V&_WieVtw) zFiUM71!fWB7A^1M$Y_yH3gae4W`|rRD44O$La#47?BAg`#q~)kgkpF!nQ-G6^zn~{ ziPMSq(wMVwImm5G&ihYa?EUW2l?{U1)ee>Pk2#EcS=yTqEMe@%d=Va9R*#kXye$Kf=ADsvRg8wrm@_gJccBy?`nDymrnR+pucQijrH#d7S5ciu!Yp zGh%4LuV!yaO-JWd&j9DAm~bY4duQ<9d-`f}4j7xUakc}7vj4ci#q6mQ*z~$8L&pV* z3|d}OsnOjT_?W_MlJ0vT&zln6oUGGK-pSy39p_7N5@Qnd_iA2Mw$kPCEsR%R7LMao zYQrJJjkC`>0{4;CZ3w>^LXMOy9|NBu;r3ycNySh4-@xt3D@ju({aKwI1TFuyzVP~y z(w)#m4+9zJoZOhY#6QxQ6Sce3CKF`?sP$hsTt~*OGvM=e)h?9hHTOXBejM?r(V_tD zl-o757S#~FcSHkzAK)zsyBuxWgtV85q>-avw^F`yrt>rCJ4u$>=ucY*oL*{>5A{59 z`eEy6c>TD$$7=0l5JQGBa=o?YcSYG?Ehd{jifj9u!WHL)>IeVY1*7NlB-wnjR| zK0G}4vhr(32WxlDH<{>I;#S5Q3#b3G0;3Woh?OAyO@*cn+Dv^p-!rv8CbjP5_x}DC zov}}KuG7W|c(Kj1jh?bBlYN#N(=aPAy#V+iEUNu=R`TY3srQ8lU&)4M_?t%04e^WF z=@CRah7z>M6ExWPSLaf4lCf1oOpI($>U=%<_i%Qc>;{{zo~MVGdD2vxs$PQH!JCfO zjaT6CRk^ylhHlV@Soy8gb6-ILVv;;E&GOB?2}z%=uZtM?+X8I~Yk!HAenBkm`J?C4 zd_&^(x39w6K`S@IgSKKr0U`;*&=5?obFIpay_V8ufmj=-V2a_mS6zyF5KXsk{IW_(MSZ<0ua|Y9td?u<_#ip|0&k>= z!c;g6_PLJXWn~JDY#VGg&WF4s+Fs8UBYMaONx>FM2V}0n<>LmVagxc@3K^d0xHDs? z?7d77=Ekaei&3j$oP(|QhaX%>kS*`dFUN74e<%Ks>VnJm{vV7cV;Q5c%CkoX26sHD zVO2+`;#8OXInngn3nkoNuKgEYT(`~SdDf#d@|U_;*v}=7fMI$hy5H;abg+Wmc7e~I z|4<5E(DStnl8PAk1ELmyQXVe*xE{tt{+L#o|4P^lBrJ^V^?(%^^>^`WAP)1K$WJY- zX8eFM(U9?OA8e^TC^DTl^jKQ1zHSVZfw^_BlO?ec$oYzioMz50zpW3gkUdi*d(Wl7 zl2WhF4+Uq{)$8}yD8|{IgH*+3^F)0Aq)eN6SiA7EzlXA2+$nsnl)OS0Rqupmc@7~h zGZbB_bE1A|t111uX_zZ#&J3539=YQmmj|;*5d-FM<#Gr)R0{mDh-mq;1;o&t5x6Rq zT)U*`K2eGrJOX_xldGY!%e?qcn}u`9ZO?o|T>R9kL^C0XQyD5gG_9wmI7ONqqt{*; zJFotnVi!NVRTt3GyQ8YlAF#H$k+duMj+(MKI=TKe_%_3jhdy0bAM?#z4Vcm08yU3= z9_k(Usf=k-Zn4|K=SV(D&WqrhCxDQ6?Z8-viCkB0fMa8;*=1j*-U!Unb}NAe!jCzGLzJWapz z-pWEd0@xZfp*Rc8IN=5`J5GfImHvP0$&DFGGj0j_HNdJptCDeWX zeeTe^h=hCN^XJO0{7?D+n=|r;9^zOkgu?49c5$S4IserBJ%!5GdJ9nxO(>e$i(-s0 z-PPa_USDL@{=}SvE=dciWOV&!tNUXQ*P^nHZ+!$H)df4NHjC@`g6zWD?E?;cBFnY$ zaJ02Kjp1q5-*9>83iQNlw#%g(s_Ti@I zYKlHG+KD&tm@^vhtwNCRvR!Uhj~a|1q`$;=rL%lT_W?v8kl#Jn&igVJv5gdu?c<%U zJw?d$y-Sm61+qER(14{~*X_TGEhR_#k$(mv>?DG-XldDr4&eK&4Na^kTMWXn_eEgZ z>sD`$j9x8*j+8C`l=+v6I!7a(p%KeUw6yvvky1fnP2&0w-GHo;&GJXI`Pl~y81FG% z751}{KVkUg(Q2{g$q|~Ua2JLww;M0f{k2)*jhzcp+uMv#hs+ov9t$Ba&I-L6~4GCC#w+tQcipO(C+_%GRLssS6cWZAU(O-Q~m zX9MWSfCFn$7CqGb`;o(Pq4K|my2m_!g1`j`rraP;2MYOt5~Uz3Jk!(KvO*oI4_Cicd<-0Ga2x#kvM6i z>D5!mvf)%gic~9Wl)s+B2n1%3S2iCD+990(M!sr&osQfGjcLG=1y3_5$ehqPq`zF) z$T7gdLb+bepm(D9D>LgKSU-7rj^~n%so$xI8V=F{-x~Y4#qJ-Cf3clEDo(hCU3*g%*2C6nVd|lb5;*_$Y~8}UYmm!LZze@^UePAi4PdF_{j0&# z<+ke#PH&j*oU`1s*dZ1-J$YG>p1*SmF_McTRl5$VbA5vC2-5p46qeu4b+F+q=ROOThAkEfsP4A=51|jPaIMn#)^3Y7X zdYj2KH$MQ&8(yg~}|L(gE}lp#xd{)%^O^ZICctq9?W4FoI*R zr^iyy8827^+91T#tJYw9xPN~8 zZ5JHDYp-QNzZX#%g>V6&^#?&`Gt*$bEYKHh#P>%8%F zcWIzge7zJ5v5SakL86fJjJ`^xRM@iv=+g>T2ZN5xOVb7qovJbi9CbCz%gfzmDm#kq zO4wIv;jJnL^UpDZxILo}Fz&nV5_V0GP$LzV1tAQ;i@M5AjJQm`0SILZn^26)3F)Ta zYQAlnVQRY&z0a z1vc-e@I%*re6aKEjZ+Z4(1#7}1q7@u_L`Br1G^*qJGstxQLe}S4e2xf{-SeJGRR6GUcK$V? zaHGhF_T%-U+TT5Ekx%P0i&P?xM)gGj1A72aJzc08qvxFsHm{iB1AHLL%nM2s^{A(mZ61IP+~3m7xxAd*pji`eNph9yI#+hX2&C_l@(Mf^s$MB|>hC?vsUsx}*PU#^+lke6 zU<}U$$;rt<4V?VzA^dO! zecV%wX#cQz0Jk4r{~Zv=d)TQlXyGP9N`R{tQ=7at#ElAqg3?=xf#wVo5;QHYmd}hv z_){Ubf$S8YHQ((Ce~AC<_6wJX>DW!f?EU_N6ncwa76UY(>(5nw7!hkdN_U47O(pM* zq?6L8b*c^B_&xU&RG+?y;R&vfiJw#m`MHs&^WWmA_P%F(lMd;=-JGk{$WLI*Kg(bm zcjIM$FTIuBOr1tX9GnRO7lI_=j|w~|x^)m3>$45xcHcWYl(V8=79I-4`IOx?L&$;G(Gn%7?-j-M@c)e4y^gv8s3;2_8ZY)25Z<~p*tE=r_FZ}mFCAPvSY`yAj z(1gQ6CDuN$o<&6iN5Byiiu7XxUnRnrU#_7}MD}POdh4FioY!8%$2Vi-#c|?8 zr5C9?o8-kFwRutd*Xx2#dr8p;ipA~felH^TCw)9t`U^ZID_9G~ie9$V7o}tbwEu>F zJF9>U>ouVE<4B24+K}*Q(ChO&hZh-aDT!&zvh6L$|KQ}m_42|>aP^N}KJo@7Cf_x^ zXaDbyo3sDh^!~pX^9#drr&UqI7P?f%$yXLp*70P#;5UiPC$Vjhal&SS4LM^D6X~43 zG*{L|_lZdPJ1LPS(wBB=`0*!Axu=-`m zXv|kknO`b5xd?lQD^R~7f$U~+1E=>wOx&HG9W;#2J<3-Po$r?vPJL7~E1P;Z_#9#* z6&>F}g-nKzdo>;TL=A0AwS2DE`o=xbAY@Jxx+t$uK|2L46K4icPNmbt{D6`Tz46lu zBkXAOJ0jBAj%;8s9QFxRh75bC5I5-s@Tyt3vHIm??{AG$)^VFSS?c+S=u$!6NUd}} zUTAHOO%Y^}8TORj%8GG_$o)Xd-SN)xt}Pb)th;aViN)B+iYz&HRew`X#kGoE0$e8I z(}Dm@KYvKVZeYUf(V=n4Bq34^?0LEu(Vt4a+e@|4Isw!A@x!VPr#UIj9s>d6e|aZ(Ab6wS#ZL&$~=1 z3?gI1;M3KM>RiSm;f(S0ZGDCzyZ$m__{1+(@?H2Y(x)#Ndu*BQM}EINQUg~py1|ih zY(@+$DbbcnU~DdEYdMe9yPd(CS~XK3pBqP_!j;PsL48K9QRa+)17K6n`X4~;IqE?& z@12}EyyCG>W7sbvLk-idn_j(2c0zo<_Bgq{{ylK>z!2y`GIR z{saHLF60hYG|%yw12e{qMc?t`Ox*@tIcrxd#ui{27DR|`H!hP9DrGclCT~;6==V99 zcZDyfHm_SWOGQJn7quLr$6{93m1?9#Nm9`$Os(pImPx%A+xRIU=L3UrCwT$3yA+ua z++)!g<<0%MKhN9FDbv69ypE_+uD z=@cY(Wx{oadp4`gObB#+!+L@8qFQElq0<$zeN@W3%sAh4m%0PdRm^rTXY)$Mm~S%= z;Yf1Kv+L=>o?>LEx@FO~YJT`MUY=W4Z2cMl1Mu!w(jML&h)J+Zw}XuUo3K@$&$AnP zQ&Vz9b+eqi9ogC*|2_J$l2r6FeNpJ=(&n68*st(t$Uv8>t!Wl@a8^Kk5z?m9kBJRS zQS={cP4?g6vXd_$e_N>&%b=lPL63-X~uaS{?uN7$o) zp&@_=d9XBgJA}h}yG?*Vb$R*KQ-??w=o(hyTtwV%RE+pFJMU{Tk6V&~>fGqylyjCj zq0RCwZ@j*8zqQp7%Dr~+US^$wWWUGAFC9E@tL-ktUW23L=Usu1#40voV2qqv-GWeS z{*N%;TcnQujXbUYZ!zj^-VvQVocU|TKDa}XUQOeUKUx-CiOZ#oQoP{5AB@LyO8!%* zOc^@pW>zzYck#1{%6LmZe`FJ6;KdR5k*Q6Y0^g#QIIB5 z6Nu76M+hMV2-uJj1XMtJklu+9dP!`6ln{F8K}rGy2oRDGLdbi&_w)Y$$MYV;ha5-v z!UwMVy4PCgdH&X3Rz&8r*x1PPAajH0%Pn|X3UkFKTqni#tI3)Fny4-;2g>>@1;J=v}W7a{J)3cL;a z|2!;Rfz9T*uhq==fi~S`ybCwo>J&6JN-Nu(fbv;||6{^udu+&}c{WM-&Xs@nJ`4iY zh(1_l-1G|+&or6zSaWvmCD)|*`(E*)xVq06ao4qH>Nbe#0WfDK-yHpR%^w~YLKun}T(79{k>$m*S) zDz8YV*)knWUoQ_xI9YD;G-NvRayAUpWO!WHvd)Ifaz@9Zd&$f{lygzZna65I)WeCnljpEERV)SkM6#{4fhoWScyavr|G26+ zb;M)W-JjF-dw;0dOAa3BP1U@Ae*F|8+Fi_=H%*i>H=e{=$r*ev46LztK3n$C zSue(~RMK3>4vo~mRh^^iob@oJL~(@qCT8O{$w1s^-QOF=sTiHM!6aB*m%YG`48;pYm)&m-!$*de3w$!+|7 zhOSSo|EOY{ZQJxxD>C96;yG;d5b!S?dj7V3V~{lNY^J0X#$}PW6JeN98KClhl~fG$ zDJ|*T9^4Jwcm1Ker%3uSg&NM{I;LT6%TDGEalOcfi|B`FrmPrGT>tUk`bcWJ_K&ng z?=g?(rlf{ZxVo7VahJ|NzC^QwRC(d3ay2A`xC1V*t#&CD(v)*>{2fjE$f_*)Ov*K{ zD+Zab3f_pOQAW}}XD)YA2$nI@VfNRKVlNEC`UV;wW;pK=3%81N1Nz*nlmjAjsG8y^ z_CtJZpt-sXa&$CjuQe=j%4Fy9|EJwfQqxpN#)fNV5I`@KZga-qr(9!w#y}?QpU@s- zYA#A>zLr_bCfPenb=)S`#o!HW9tPSF=@u%mIxJm2Q0#P$kefK!+3;&o!HL3~rvJ(>%|kcYB_#S zx{b=eSawRHl0kc;NVTwq?`q*GtMgwh1I1A$i3U+WE&wkjgAw#`gMt(vvRn<>!xct- z=3CI)PA(XvDZWTaP>U~3=bSrYH6991yIsAiukpkkTWCST>@KNvF1dC}VhIwX=b#{LGgg|J%d{{kH)Mx&DL$^;)-@Kh7 zJ)*$He)w5?9D=Tgq)&kT2P>N3y-d-@KO9$Gkjrha=7R4+HWg(_53_XBs9b zr`s2iWu4P}C>t@ctj!V1fs=01T4uOMGr-{O4cEkFABq-KL4sWJFh_wo#eEcXOyUyL z_Y(HPeyWqp35sdw+jx>5tm}ge$M-hK*52kdi)(?YVn8?aM#!TnMc>za^m&hBobl@> zO1qQL2gS#j;lwLPSNHzqKa|H`v*oA}xXM0E^sy`MyBnYXCmA+lr11#>jOv#^7ej-8 zE%h_@tHO0imL?^RLC4g74)it2bi*CRNAs}EbkvyTwxTO-vx33DnVKyy`sbShX>(Ro zjkd{Cqq8Zch!Gbtg`VGBKn|kq-Rf$d|91F_5jJ&5@t|fc_u}G~m%T}sir-av zbGUinXtc?5n~=7gTh&wc$&hj#3(u;~h#Bu~Ps#9Y743%ve%)kM3lIoEo~c@R*Xp)E z^(Vjk3?rGnHOgFu9)HEhH76`kUgaYs>64N$!>71zm5W+63p2aR0}2gYeKR>0txK4VY8&jCx_eQ~i+| zLd@J^f9e@tZ?X9Z&48yRETMf7B{g{YGd(E9G*xMcrAaBFIK%7SSJ;svC2>mpOm|v~B6;)23%?A#^_$PI~`V_-o1XRjz533~HZ--+AH8 zpC&yZ1U-G$ik15=d#16rRrFBZN*n1-5rb*67k}k5z|qLA2pv# z8{*7=K>r!)^n_E-w&_vZv@jrV*{-vGJi3Qzd=hatG2xN4CWMO7unpVXD=EUBoEY{H{ZW#?`2b4bA?mVT{}I_ zMxOTSEqU9#)IuS@jgj*1prt?Z;Jvr-=ya9wBE6Qz_F!9YChGGGgfK?+x*`kjvK*3M zl9T^6?yK7!J?^`0(v|z}eBs-AwTbutnv6I|<(W?glqV$`+~_-c1z|iiiQfX+=@t9hMf1ctsc=Yzyo>8^2u_=_SAGb9; zBpiH31v}J);~>7mQu4MNjo=p0^quDQ@SPjea0-+)+Ixom86b^#QvD}rJ@8zdTeuh~ z&eUC3?6d+Qd>#4L=$AF-x|rSwS4%Q*^|vNb2XE%B>MyRJ$i8N`h$m64fS$pzA0^` z6&qnQGGbHs@L`q|4ly3l7C9tcyYjZ>fs=c}Thf(!fz)>-T?VdKCsRN4K4fxkVR9A zaD%Z$HX68K=ZA7eKSlCSjrozAlI_=`pIyRlz67;w9o5_B5X$Su)-Tuw{_&kjREV!a zfqWK$h+5c{^|UUUTkm3Is_-Y-^QAL-;hq#d&M3@W&&(A$?ZB$5yZgP{G=b~?t#1zT zpg(-wo=u@hVLAtqwcS= zCh#++*tQ~}sNIu#{4a3-h@fAAva5@lda&$@K2w3^roeRomJl!IP*w>qG zR^%VMZfU?DNUY_4%T_&2*wwWE!3z*9n~ z@1GF|vjmxhSV#63z-9gt>cx7;JsNbsk4X%YFqW5R7i8f1bwkS(O95KnTfs8c@8uPf z-z?drog*iM`^fk*V471h8x9JkP68GJ@0YSRDzbm7iJ2-0p938pTu9Bd0nIL$=Siv8 z?T)E*uJk~)jlsW5*d8^qIrPa_sLWDv1AcH`hr_w@Ve#_U?-9q| zw2K&bC16DHCIcAAYmlI*VVmb5!~+xDHALm=7M2mM)Giw>9NvT~J27 z^nFW;T(zD4fV0puONDGWEgr!3)CKcr5aZ1#_u(!HsX>fHy@be3SGC8iib=A!$EBRIkbOo2nwEah_jk69m)AE zo;P-6y}=6gI}bSz#;z=uN9E4-Ug=&WGA@dx_1ydNlHJ(;!Q`vOUTgjJ4f}&!?;p>f z|94W~D)iHQu4kcz%%5DX8`5Y7t{)a9XlI<3ng>gnVfl`ADt^K0pvk%bw=`szYi zyPGw?f+i0tyvU7=Vo7fsqzdlGOCA()+UT{Aaq)`iqNdDU41NEv#=QGF3imSzzzprW z`Mg;T;+mMxme4^z!s2Ns7Mz z{9ShQGRc(9l23Yg_rbluUChgNh;DZW$@jF9xqjy(D;eX2(cBp6!b%Ma_kW&?^#$G333%j2tt{#9&6Y&gpxzznN#_P=xJGR*+66PvQ9~74 zxVo~yN-YbdWLW>_-LU~IuJ&mcajE)Q`9g`VcD8_W9y{gDAcEA0u6Y0`{X*f00 z{l-#hM-M%Vv~Pg^fy+@R*$^)F79;XQTE=X;-wO&c_)~R##8mx9taNGM7uT{X zVvi$cO;=IDvr{c&gM%VHEFvS)m?Pjbj{5!G z^Rj#ILvVz0&()MX$3Su2xD=Zn7iBF>T>f1U@zlh*WbR-C49VZ&8T27&lCZtCX`j(VWHEfy8-wT7?{U-l=9OxKz^1!X? zj@MF^Dq#Q8l@)n}&r*@|ba+Vs06rVfFW%i=E5Gsla4FE8dCZgzw-_TwZ0*XgC8_TVSCso;PnRGmZF zxl}tK!upc6UQF3vp_NsYj+}uB42X``E!wZEr9L#Yr)u}|ZfLv-nL0Az*O@(BY_TXQ$t!io>hE8~iK+zTXgLAFhpa~?_^g?g>zrSAr9jvc$u@n8(G{N$W zR(YBX{5aSV9LzV5bt)4z&>JAnhnW^=VY34GRoYr?2$(xnyE96^+~COH+yA-1!6 z&j4&V+cc@pz8iJF@ppj!r3bp>a>c_g5^-iPj8Yf^x1cIIR~$4=_4@q9$kBVIn3R<( z+mq^rnD>U~OwwZIkb9P;w~>cBaGi?|^B_L7bTxfrn@hVnO`!mo-a|#>Lnb~hu z?PwzN+B@?686i8pGn5!i=b{uDLgTOiR6mnKG7m8audqU(vu^|F%YNa&oPS>#Lze4P6g| zLmq@7gZ(3D&K{!#iggC9ET9%cABgIKryFgfcA1D>u3+E9#}WL_dNHWbb#gWXdNh=~ z^&BvlzAU*QhA>Geeb$7(c|(sbp|<|wBm&6S4t@BQpVa^UT|c~G9u`YG1Lo5neY zx$)i9%fD)heKE-o%1s}3U{Y6djRjSdeM&&x<8c$Qzj}CD2yB%t+AN!@nB`M+JsGw> zJ}P6pOo#HC6RvOFVXY1rK5ff!=)LC<3OWL_NjOIgN*P5;=GaZll<&0S%g54!wiUHp zw56$j?AGz!Z^afPnM`Ww^r8Bx#>ET%H&%TfQue*ULj||tSi^9iHP^-V?)3OAs)Mg` zn!+`Xt_k*nqUeJFHm^szYP8x|s&K2qEmyeqwTlo0yV*CrFeY1J?dhXtpbGU zc$)klB(e``-n$*28;9`R+=)x39MYEL#{ezA+w^5f6_C=I7ZLoEYE6=Mx5v zXjxU9=Ym_n!L<%gP~53I57ZxsnKPH0xx8~VqybEE7I@bmi+q+ozb=gUCkrIN&vxXG z`eX#ni#Tfd<#DCt#dc!-f)(ZEEDNOgyI#ExVkL}q<1V2+wGXG7ZaSEnmhbPR(g6e= zVPI>d+;6jYPb~SFxkiPXj=9wp?f0ihzPeZ5n<%FaY~dJp&k4g@ZuK7_$t=Dkc zOUhYMZkVZ}y2MO2kBxep28xfBH{j7TC~a;*ASm>GZ>mXkMbMyvDa8Fx4Q$VN-P2zj z>xnvM(kObvs6}f2v`ko^Phv9jH@JnaNUJ3f z-R;-o43j|kJ9hhQWb^v_$y0WVg{`PCLy2c`wMK-eVXL1Hj}V|xCC65K1tKm3TQ%B$ z-td8)wRJ{*-~5E-H-A3PC3V7ntR|%#L3cvZ0ikQu$NEzG<(@;|zNq~x?OW$N{~SB{ zx2R>DmjHLZ;VN3*J%J`d3>aL+ld4+i#$rwt)h(-epO|DFT-bZ2b3w7kjrm*~+SY-`4{oU#K5==~GT}E_wNA^4|>T=YwL9$8Z00 z5en+}+rn2GpR+@LtyNU>cy0;ZT?lMm%Cevne$@Cd`sYc6qNvfHq~az{TSyo~Ak7CN zelxS`6Tdhlz6|5*_-?NPdUPIe{r>Q4@MFj&cWgzbwM30Rg5^-ItirGjP=?fmd*;AD z9%B1;$Nk++u!jXVyX1b%!*HH zHyBJ*-p{R{2zo7)I{q--WD>wPVzM`~`u3+_tW03wCtGf(PejP}7ta(H_X-XnP8N@z!$uH8e84Fub4>3Rs}9k{3YpO1 zo-Dt%WutGnSQqR($r1^e&5*}FG938WErZbSqezAQMc@yqANAYlZG}Kc{wF&?6N`gz zs}lx7y}Dz6IC|D^5?N8ylIL~2ektwcg`wU{cnmtEwTTdd{|z241JGtiY6^R{zf+_K zH1SL)C-*+44zqc&ezMN9>jc^@2MxJHR9IYVc8=57YHJ-%D9^331ym25zRLQowU4aP z3~jI2_sUQzMpNRvszE|61f$#Xn*5v1!u9uI|z+QA72l#k4ymis`3?>m0$L3SNF zk|g&Ce0qgz=R9&U(V%o*KdhpR*ti!vnMNM~8-^JCh4Z*)T^owoa~YWGJg0?i+WF`n zZ;RhXE{1Wezy7f=08_C4mAyZ;l!P0${hTjl|3|$XzzJ-B>FFTjL%Xmnthivs%}>X> z@wTu;9;ap*F1C_e423Y7kunkNcGG<_vEAUSe?UG`y5QWHJ9!2_gR0+D<@Nqk8cF}P zixO&6rEQ-lUFNm?+akQabK$N=sE6~@qvB1Z9~10W1)CB06J6Oqfy{YN0g6eZ4-1e* zn21eTM4J24xN|7bRcd?S39HzovHPNrYao4HJ@|{~v2H{5Z-qlej!r}+wgs~SqKajX z>p|3QxC{0oH{tk{a@*y@sgMfB-t0}HQa!Che1K_F<(JAI>5%#=f%!h zTG=NDtacru_)w$b?UWQwj$z(u7k))vupv6^7Vx6Ps7h1kA$8G68oM zb=&ERg!NGax&vHE0|Ik((y;gVieRVr@NB3V@UH2l^$Gi?CA0Z^u&mvUC2`<{R46YJs`taPqQ+t!cHP5k=S7;~2SCZCMMqCX=XFq=%$9 zp?TXsN2>??7<>E80G!h%ojw+}?U}tml3icd%x9I4Ju_>GnG)CrDU*|hre2U+? zq9=yxS$`qiBtneUoXM(aS#JjOc^n`)*>Eq)RfMK7DJ-FTt5XV5J29%^)xB^<{+7`= zv}$@(vZsA(kOI9VVJv=75o)?6an(S6JYUhd`5tm6FtwiIA1*9ipMJ)5)g?OQds9Z3 zUp41x2H|n(1ofUO;FaFH0==+^69xO_8CxChI=l#3$S50nN z6qyX-XNzY#)|O5IntL;VK43ZjgdYT4E%Wfx_?RPt zMj#naX-(U=ED-j&AIEP~2}3<_Y@g3b=TvvEeUoK1`GBg;F9DIJsm>dE{M9dU!3$3h zr@Ma+V`Fu9cjw%livt3^f-$3Fa;Eii0d@ZUzG$lkVImYoLB)w?&`n_9R#!w^*VMvv zruSM5R`ACi`7OFTtHn1So> zz_NHok`cXDVTeHqz%p9F#Hlt4esPLiCIt)ps2nv9pM%sfD_@dW7wPh*x60AYJ7BwhG$Ju0_I8CsDT#b!3I94B`}Uh(`6n?%wh5pBozI%HRv1FChl zBS$B7PGv;ttOh7t>-2KKIpP>Q@g4@jhC%#L==uN3I?{h>+;-1*IU_+6k7A01Ev@7% zFUYWwpR160)urR@1Pu|1p_)#?M4{a>bj0<*kLsw@cr@_L9-upE4)^9{la5f;xp;#W zpna>v#b>uL_v7hdI>+_+&j8u*>>8rGNpL^ZcW_(FU!X_a2TF~|$+eaMH_V#-|32OS z{U$ACmFr~9*m*v)$8?vk*HlOqg2;Bo9rbXJ@eT_fs)sq3JnBS`SM+qn88TxbpDHTb z45OOYwbA?KP%F5bsqs^xI|sd_6klDGrEQv2mW&;IKNp-UWI3Klo$h!8*(vGI1zy&M zBt2GzK6=ILZfmbH4Y7)Ubjo{Wds&-RL0Vc>M&B@%Aj@5wXEJTp8=sDMN)5%!#OGWQ zE^fM$Dr`8Oss(*$-bB}!T<**CA0Uz`C4L>grLFM=UFHAAR4OCus{ifS`joM$?Xwo@ zThe{I<#*ytnj|c!yu3P}K197QmP*kqm3vn&Ck0AZUTY6|l zw)T%D*Hfp6kw&Ttx#QT=-Z@T4+g8tnFE=YjsT%5S+pl*ul*wemmV0TNQ=rPbfP^yz zq!%XVbty)hTim}qY-`HN>z7fe=4nR&-f%kVVuU(IL;VqLH z$eeDR!p+J)HIO(K9PUQAEF1XclW%~GTQwJbsw^mDV^m^-^Zo1gP!DJbfJBjB<&67G z!5gMoi9G3kn7O{gbh$Ug?W3o&MxN;5y9HOZpf#y_QSN)aMgyzW7sB@!8a!w|M&Nur zZ^)F@&cyqz+kn;@WH(h+=O^YXu-*$^P*s6#8iGmz(E8MdwWh;Genfd9fnkxs9Fqiv z#BdU4p9z5)@BBPYPmZ6Gn96|u`E|DsW{`UTNx91p=M4YgC5&_#pZ)Om>!Fq%8^Gy( zJJG#?J9s&9sD=1)+~0KGH;JfK(H1gsTTtPyKu%5=8UZ@I`#)=Ah1H#Pe&-IW3g8G^ z_%LFtCjuw0jsXSrsFzOo@zv&B##J>AX=hNDpwS6kU(ex7haJ1h;p7BPG(@hj0~m6R zw95r5Mbyj4}apd^v z57T|T_(SV~wWr4ZWiKc8HMS6-SFB7@2!Gk_{or^fTo5zc(zWxtf5l4l@>^B0f|Xju z9wcf#K!PL>#GihwSW`YQvN*#0ojlWFLV&^I-oxVw(QAlzIqmc7-I_2|BCdQh?{JF;;jKeJD6UtHZtZ!9dzp z^DUxwRGemGQINxl(?TL0MnrJq9pzSbhI1%O#4KCO+J{&dOdow%q0Cd+FNdF?R; z#0*BVP(o_1>t~gm@i+aVpOw+eoJx9_-B$H|GIEC}H7>n^9rRDoK0H-JqW9osITgWv zfhYWg6sQHsA*T6G)eZRSVBrpwi1C|nsr6Pm2w*FlzHNg&)xtX1+Sy=95$pFVxm{v5 z4Q}tuudgLd@IU5nub3+PEaw?*=^Wkt(Ll(XxJ&XP&PB(@QcIOWJXv{7+WT?P(SlOd zUKJW(^>oJ2oHcqDMYNM~m+MLI;%63n_cEE4zL3KAbwurz{;w=-oGI!4iI;IxZFNlB ze;dLp-@X)(t9Pa~80e*5#gUov>Bm*2MbLxxmI zdc}l&mi}7f*9393(1%;C$?V$rFIfq?dygfl!Iu zXWEy;?@L;8Ud5c?bgfQ4!o27TFeBqgugL?(lBH#35nJEBb^XE%Xv==)e4uV=akD!! z3O@GF*e!aUEoe;C$Vh|1$Il4BOo;EhrqdaMY3}$8 zgaD(F{ESsSOmfFu1u*a%Y#-Yn;cK2!D|gEg3s<5~hHPz*|6@0~VHB;=w$mc*wP_t? zgYUjw8wB!jbG2x1Eb%{Z*e6kF|HE$Xq&)j3DzK#DNWI(mwd_qn-yrkk<B?P~aS|pzw{R1r94`}Xa?>Qx=&Is_g}jGPQNqh)3nV2d=63w)+)t)?U=TZ5G&4_b zbX5zE=l}{?g_D%WwD*%y4p z{6HY)U77DE9&aZ z?3`ITPDm!vakTNaB#0z(MJ!ZY*YiUMdfOg7moGh(MoeldOTO6N9oW?8)1BWN8|2(v zNA_xJ_ANID8&$Xc4Lpf^u~lu$9!mDr_jLRLld~RE6<9kG<4a#p2l6;{EMa}lZqg3` ztjt48uI^m9|4BORV<#RO2RPmhPg$PGQ%^(r>|nXN7- z&6XHx-693g=n$|hc1IY3ipEMC9=mEJc^p@83?4B_RE3`h`km?ZaIX9vT z>9LA=-lIrkD*}G$w{|nL-BEWzF&nb_8wv%-g2CF`JUVuuGeOV%@On$mOaj_jB2!{y zc%rQ6y{NiI7~H3{K?MRVsO}$(5A;;T1S^v|YF^ z)^SoqEUqiy(>`XZmb=dVh^`s4phq}-=rwPS|2w@Jxl>&P!W6rjYg@r0wjS`e^Wq-( zVQAetK2eW!0vfWV+63pFg1cmQnR>`8-G^g)RUof>rL;|MzFcoul>MRMe!k^8sC`#g zH5G{Vl={R?u!iGK)>3Z7ti1FQl=wAFTtkPf63#!pEgjj~%#!#3Q|3NvZa~PD08T$= zBY4qw2&1MmK$U#Ie>6wiLTVGo(f!Yk&L_u{t8P>SmaL}Fewq?v7PM>?^OOGgFX)*! zcNsxr-5sO85#{AfP+Rw2qKXor#k<;5cCG<4NOH^G99(}bFDS(~d373J1XK7D@;-iu zIQc!4Qpt}(?2D0`^nHN#@*mT=8kHq&Hp=_!F&TnydR30|sHZ}5Mvr1{0$KULl~`|c zW-6LMi*Q+?wSZ=^!L z+0ynzZ;<3=6!klGDe$vLWiS=6I1NQb-2^9`EzFX%$nXrRmc^k}en+$moC@2H&p?&U zvI?FFS1pzUIZBMq$6pmF7S|lt;crf%bS0`y@=Wns$Uknc*xFS7FpO!kBroL}sy9NR ztO_i`3g?edFVoC{bN@n&*p!uaEBtL})cy?EIzTM9S*xsE&q5#&WmQ$ST5~BIgAbCO z2LBY@9<#Ra{*fmuJ{N1j$-|TI z{McyXK8=>q_7E?gNiNIpFS_cBGG{{}QMzc*bP00wSG^ z(_kK}`r*L1J>&lEN}q>oU4UOzKSr`5fWL7#Y_`j|t`=372dUaVJ3eL`BUbvg6Z!*V{ z185a(C0|3P?{*%OEV1y@ya$tNZOBW=i`yQz#Kcb;QMvnzA_8z=jAn(Nyf-&P-Lc-g z(6+*1dEG46^0C3QPr77vYWkWp#f%@uQYTISB`kUER_1Z(GApoe)t{Ni$sW%SrO^s< zZYPLW{s6zWOvIoc*x2NMdTkg28l>qiXUoEu3g3QO=u)K}NkYQOwWE7{9eC6+?Oi#& z{a#!b0&#}rb1P}S=4UQE`nY(rmLFEpPtNlG}}T6Sam1WPcd{AFzy7>#YZqw z_N{Tp2qpyUSe0aMV3=s2KC>tBqxflUzhtoh6z(O+*|)0XIz~$#6w_rAo3pe^xpzI= zhdACV#MDe$wtzt9G-v&Mo&F*%2S`~riy4y%6MKG~>H*xOGQkptW{72|q5HJyP@AV^*p#aIcjJ!dd64oo}=a|7;SSw=2$w#*ORa3Zwx1`e#7I>OZgX%0s^JO3(+2OE-V^Gih#XPqe8D{70k=h zx&E&2l`h>bBeE{VqHpclJ*yLrLUCL9cVf({%qlG~8oAvP~tTKhUp=V9D)SefHmH)EtD8o_pI^PygIKFvSa znZbO&hVD!CzKRNeNAOvU#FcGT(%`qd0iNq~?njf76t2!wf;KGC`|zBhKx3(V0K}Q< z5+Lt{Zr^EJ2!DfHENj)c=uEnd=yE}MeNqCSEabp}MLNN2jL718ml85CYohG!Bb%9+ z7WMWB{oQ=y(za5g!0Hdrk7-+8&e;xJBT)9m)gC?phQ&@)rOhc*<(09d&QhZ8U%6+H zeHPfBUc04dsII1IL}pA$Q@#@(#S!v&4N$-%=FQXr#t;NlTwnie!Z35^n(@C4k;<#M zv6+e7ane0Y>_MSzLe6y)=-$GSFw`D%qSUL>gU=Ebrc=PQRb0GOd1I|R9z326j z&al`s9HR9OEdBUer!sQG9Q^y46%PfI15XMcLLit<#r{+@GVn&>jZbnRWFOZkq8Twm z!?k%ol%K!!Ql4TS{8q((YT;hK<;$D+{CCAw>I)J<5_%J11x zGvwi77|DG8SZ{sj*`Txz{oO`TG(-*tD0E9OU5+hM9mQGUHZw15yJ$6uS|T~OvC zzvv~dBbU1N;_|rh3c*{&q<&ez^bFmZ8mH=CB;2KBVac{FOS3%z121x-zyn#ORD1^i zxA2O;-ZtS26Q^_QZA|OY~4b z%I0E`F~Yt?O~Kdkmt%Lvc33akG`@8-YJ^moJ#szY2sqUIvfb?{`=7KqiR3SZ5U@RF4WIchs9c8_BG@|+fv4sy=l*P7+ zr6HMH2XKA8Z^atr9-N~XVQR>`b56jrsj_={P3KbL5$W(TJDWE{7@f7Uo~Rx8G`Coy zcKUrj5o8n{S>losEI66ywZF9py6$dXJ~O?-nhuDtj%r~#^9j}ll{e75!uhSmV%M_0 zd{%-FzZ)DbVmGX{ESg$%CFF>jgjS8RgcFYQVf3|oqF+6EB-JSwy1xNi8EQ)%t#T}M zF^XVZe`S(-~p(gsFfU;bYDHwH!TonY*T#!sxa^)8-T*aH3HfqRsjt}6CKmE@X| zGjt3bphT#&lB|@JPm3w{bguWay-LZ<(5?+OE4QsPb_8z^+rI{~*!nTmqiG~F>bU*n zRIX7#-{6A5o;e!R3caj$YEe0(tY|T=ZlX0zECWH!4OjR#F>olO5#8IA+E!Ke!DNJLLtlC3mM z^R8X$^16h7zm(2;K^Vd0#>9DM>qRq~JHdb#(HuVCbTvzOW!(KOmsq7v_&|Xm>-u)4 zVCwEG!=P6>sWC&J@O;FgvND;2XCoGc*qWy@&_vyTnOu10HF7l;pzH(q34NhL3gI2F zKnjsY3A6rVWm1d}@Ss97(>p)$hkj)8ygY114rq|qp@PzkUH__^15d{xhov zQt?>*O3i>qh}C2ZM<5-K{GWL0&M#*KE6IrWeu}@>>x*SGz5H~_;9C3BuS1+d*47x^ z8tGEPEC~p5^0|elb($`keTcjU*z-Ua?7Cjg`=d7k+a!EX`=dEuJH}?Z(9I*gUAy(T zAGOFD!EXJTiN&yg0>ViDzNV16G~xpqncFvpQ|?+RUtO}!3YCmY&QqmwSEr@?bL z0(~rDIwUb<%%f#cpM4z^BJwgr+x2Avf9J?<2M1q#uqUY;T@fh)m45VnrHn9vS7!c6Zw@icRY4jR zT8v*`+ga0HB=SCoua(F6w;9vYnm)cQc_!R`5EJW9w#<(S0A}lWBZ?M-E4M#Z9ihzYUkFbhMwmz6R5_;vq^hS(rdBI#2fgp zO~TRRwpC8~Fy{y>4EhqWS{FQUO#mdlf#!B;5-dFqlXlvD9v4h3G#CJrA(sgG4uPP@ zR#jL39(m+H6`SykS|_Gn*z^Hr*Fcvp7Yci5Q@-vnQF7Q$onAU(7FHQpNmbME+1$EK z3|+S|LwP?VZZt8K9BXcx!bqc6z{1vMxgV~^PBT|9N=)|dw^#DsuHC=lx0nyO_je;u z+4WEkv)Q}6ypA;H#G0+tq^F8O3v$ti<)Lqs-pJBSibvr;K8@*Fj6-<2G)#E-OLl8< z3^eP*fdqY%s3xvQotU&2k+4&$e z+`f*Jb|;~Bk)ES3tK;ND9+*O}GbEaKVg&gvX?=;P4mj0t`psMIojHYJeGjCn6kJn# zVp>~S_-s`e6&uDEfbQoOT7@$H??n7u(&)*BpQ0jP)mLr}7;Jl4e;lX)q?)$1kdR)+ zZC|1kE$3B9n{|W!&cbc-t+i%l|9Rr}|t!CkMfjQM1 ztZ~0{@ zntXvhI<@je+6gG~=b}bj^4&1BFK%1%0LfAOudTuF>ENZ5B&ff%g;6+!S^W8UaJyjd zzE~9JCTneEQudv^%pg?F8!wE2ax#Ih=KKP^Jg~E$l$+hKE z_P?o)R_ic;LrO3t>@AbjN&=)8A-kp59H=(`>Kc|kU;kq@eRTZNNh~rhC`)nu)Nx$Y zL27dtS$%0P0Bv_!3jKPE+Zv0Hw>4Us%#Ya*T4POk@z&&BeCY|>(|-oIb?w%`R+61e zzksPt*Erq;G03WA1hn0Gl`#7Dggx~aY@*%60H5EGG<1t)JIQutvV(0IYWibFn z1*^B0Ce^whmL2)+d>GS?V!b_glIox+-^=yD>(-^gNypH7qpQnQqsrZ(UYlmGj-Y7` zzgO#FJ*~Yw$pEEc;Q*ykb!)NZ46Qf>rOcxZUu0zZUejyjoriketrfXD@us$AA;fF( z)2%s58^Gw9_j_ii|LE&<&{o|ey2W?D&~XE#^x7!<40rpoL2k@?tKsFdsN^!g;R+c= za9hr>x%Fy|ynUcfW8cgIZ9*%l9BCzOTtQDmO&#b<6YkDG^AVtXPvI{c+UXz9aF z7e>RGIDXrx@aZxcdz4 z?rg^eNNC_DtCY{xgDeP5n;7A$y6USE^c9SAl$lLRW`3c9U5m;C{7;j1XHFEccb+97 znKMmE@B=XKbSJ@^CVbZrE!fc`k@L|36Q3W&z!V}h{vJgrrYMIWj|!h}^M^Pw0%Ude z!v&kZ#qcpc6r)Qdenx^?!t%-P4L?bOYTjdS5LLv!d2BB{kRJ90#vTuaasJ5$yAjzx z(0E@Nf~XcHY^QB$L7N~SvQi6T7mOw%2>EqHvB*mX(D^)Ay~nBcYDb|pZH@$VNQnc0 z$l~p|PvhQkski_`6ZWh|n45E?s7~1u*!@p6iCagBIav&^Z4X044?=V41OK??EU)lM zYW(GKJAkl2WMpBP%6k~wx_UXl!8~nG)M{IZu&u!|^1RoBLEEQVM%u!+`-RB@Bg+0R zS>0{+Lu|kO2@~ds`j5KJMu(t|#-2g7ntDvYqEa_qn<3ev)%7eO>?uD@I4S7vY~=+c6{xfZT?xGNwOc9J05h5bBY7;yG%PLL5^SB6 z01lh{l-iUNh38(X^m6tIsN(tOlmiNw6Le?n$VwWwXr`Iw(S}${iA`0uR1s^T<*L6{ zZ%`l9i<>}@_e9%jE6m__^`18HI7gkM@-N;tr&n(;57_~u&q}}L{@9{pN?upIS29G+ zAd_XX)buKKTDj7#*qbEX;-_WA&&Bm3+besE^}pDL)gKZ*TVatCRwlI3*48b3YjMiY zQ=hV*7TE5KWXw2q0#6Wo+*Mf#+zb&CReXE{H;8JxcrNwU(YE_%`=|euP^krHlt#`I z8@4~8IX-};ezZR~v(#rF3*$(MBlnIt;=Jpe(SCX3q&cy=c~_h1YurcpzM zuE|lzx7_k2GFXGtf_{z1dhc3irS@=~ZOVq42)Z zXk2Z`NDyl}vVw~_IU~_ZrBeT+SUx%a;=g%mU;%rSWHrP8C%|l^E!RJr1&Es=pR39P z2vOPBM*+=f*oYS4$PkrS`Wc&>;=LSuGwPQLEkU{fhVO{UHxn&>uJbzdaKd9aH?qM& z++cDHU9+nDkIQDB9DjMU$5D@OK=W$<2D7owwgcTcVT4B=q%uDmS`6F5BA_*amDhuE zFG}cv>w}{8x#>f!mCS(B(*P+m%j^$Xs{%RmYsOv=x)OUf6&k*?Qr>;PZG?G*!NjtsAw6mYY%l@j=VSNt2JRn+B5IMMVXV&f>C#AS($c@ zU}p;Vs6xZkhG+BbIeBY83D=yaz#M%ijsdG=udG!lMq#$K9vkW4_U&-0AhQ=@991Qq;cC1Vcu8;LYa)M7SH~OG!yb zhkAy#UzrqY=lpc=*R>24peJa>>LXB+dLMH-sCvSy4%qXV#|KB?sq_p@54ozNz1CT3 zoMYphzox^7;>%2GqOv{w`J{V`yH(8oWxJs(-lD~Dm#A>b_G5MR2v0M3(rAU>@K#Ds zoiEFz(s`()(Dc36kE!Sk6-3b`g1XU~2bgzuJQarV5tHBM$69w3KKjO9Y>{q_P$j9q z#Rj04xIBzwf!>bQr0U%SylI52i&HRx1LV%P1H*q4S}J1R=3s< z3pPmqv$TV8LE`V4A0GkD=1X*Ay<}ZepE$DMrw+uw?5h}I+x3#vtT~*DCpe9*WJsf( zVi-EMj3VR-gUkquG+DxnzCsWY2c*&=1iLYR)FEimDEdcZ?m!hb!{N$2kYYe1j%Yi%;I86X(858hXjg|NEVq{Totw72X+G zhBfl!>4B6UvYeer8Ve=%M|rnhc^||FE2THm08eX6InPTuXwfW~ z6Cof?*b#_&3Tty(D7MwzsnQFlL@zKS?jWdq`sDEeXOPq8JhUW3`zMnpsL-h~<9j1fo0M)&v-38s#}P#oaC;_wvH zNJh-@2-QyclBWN|*jI(c)ook;A;I0ihu|*3o#5`Sg$4KE?pC;a;RG$* zrR&_j|LNQJyQllS)WhCYd)LEUYmPa_m}}N*DOhXQyV{m(6KBq?%oWz8*;w}(YZXoj z&;G((b?H3VwyG^pS-#gQ)K%hl2Krnd8@$N&aTB*rG%Q7JiR5@n0bftvW{(y=rITxD zTXOJ>J{xbD#y5Uv%9M(WvH>>@8OG8jjAR(sIPVvjtJ~xg+ z4hJ3PSp$q(q94su#@l{# z%x*wG#EH}dTvBNBD^-Fza zg!gD^8J-+Z)L_0eYI#hjJ18hB{Agvhf2oo9qt24~{!%ASukz)^AQq@p_0ohO>6#8! z_+`4xiR;S+Ilimvs?SFefOOFK>NlX6F(QF+{bA+!S`*OFEUfbse|&(jlnzwL;#XA| zFGlyJy3Dpo^Q`$kWkXG%dZr!HH*z_U?o$2e2tIJ0?*{t$=puz0Fz)8KH#Tk98cf7@ zeADBlvcI((X(uX+mP+$Pq6&5B3AGvRqDR)qo*_=A%wp7S?CMIbzhT6PoYdf5?o@Mp z(zd`~=m5GL7F#OiJ|=qgx{zuOk?Ha^zB=pq{My~~xYUx>|0)|frF=OcF)FD?72dkS zTQ+L_O-~PcXqwqJlqeTf(91s4nCy{5p30ci8-WevQ+Ulhd_J7VoHs^Z@eae$a&2$Vq> zV#C0o1Urtk0Zb1xPdga3?`GB6*#I9e8{|umV*;lj zQLEpV8fUU$VLln;wl)%p#|U8=Ox}yiP1YO8(B&kR49^OMzUK^UVQ1&e^P1@r1blYV zbGA_n7?KtYdbbJ*i@Ib?5-M%99tAn{|B&7~E}d=Y9${tV{4wvxVXkIN}SIG|0EU}|Q{upA-!VBouOwa=N7^PmOcY$vYg z$Y^*IdiM3u1a-jH%G@0_<=TLhM@>5syMo~!<>c(Sqi($ps;sv677hBQt|p{(hXXj| z`QYDo?)01o;bjrpDQ`?B+NzvKMY17kD z=c=EKJcrBahfS5BGhPaF@_FK^Q=F3Ass zzPE@J(76AfqV=EGF7E~u=8Z?wo@#b0%`qY~YHS&B7(KM9=3Fz^Yc7`Edh2X0xZ)w! zgfsaAkq%>BF+)uvW1_O1h8b`{3Gt;(LIzLqNs;uNtd>0*6b@KQ`7-mdvF;gIR&r8O;csco4ucfiAjsBU33?+F3%pcmRkg3`f~K%7lGBgk_%bdQY81=@)+jF%H}rNiPV}f z^~=r#8tp>^Z^7uNI!yySVDCtG!75`YwAqBS!9cO9{Z5Ob>NTF6*|G6ud%S6*Cm)Fa z{fV?uoROw@dV-Fg5t`QEMmUC`zw{|~Dp<48uG$a1{2hWd`e*qX;vm?dp+?-Gvd^L& z1U*_40sgc}#L<{dh(<{HW5mQNB;ZmK`CFSwPCI1esuyK2-bIOThhZt(i@I7|Bkm0~ zzp?T5E(hW7U=&Moux_KC)H2UJNsMFIXsu`M=-h&P>YDK+Oq7=$pQjoe zZ)8av=P<_f+vVjZlf1tmrX;n?$bp`}Y3@Gw>(XCiKICC2gpbv$kH@d{ z%z-W`DFSqqNfsZGuNL!iv5xOMTy0}L>#P*$&PX2q($BspDuYS{?LtGMWy1d60uiCo z!eOFbr5_IM?KHe(Fg3eI zh;DVO5$1yck*NIOWTOq!x^h14Y8^&=IG4OQs8VnX#MfN2>$KWPS@GE!KXUJAsg$ou zvli?3{#efm&{s^aoeUs3ump8^)gDT{?4_xHf(gM>N7TbcOi%TQ#5YYP+a2L! zXwhk6*273NCg_Y@$*^jf@XW53pvtqRWa^#GXHKV)o6s1S`%)(FLwJdFCYq+jXORVe zbGNW+zf%#(++SD6-i+{w-I}tO(SgJG;FB56Ge}(hRRRjLL~-vmg^xMLyf^tJKyoey zIW!Pr$M%Ivht(mG%|6pF^`}#4ASh#Yl_O9aRk;ccF)(0cwx~}jfxT}ofDVN3AbycP?1=YkUS6M; z_{vlVz@(f&+o!nIEFRk(-B&Gc=qoDj1zyw;REk}NbYjQGcwm{%bDbyG%Oj^zfNySi zk1kQ)^&t#s%K8=&eN0>`v^QAu?2BG9Y&)$#DHlyoW{T3zvz(W{7APdN|L4AfR?`YJ|5Ckkbc3iJXhRsaF?WUUJ_O} z<=F9BaOC;6b@lc-x^VwBxf#_V+$C+^3hi`q`{VUVuyF`Vk0lK-XiZb%P6@EcdYf*3 zJ|@Rvcs4U2GrGp#`JVDgHKLx`cGWOe&vl?y9BnAX$FnbqPx--3S0lFEoFTxYtbuSV z;~IBgRc_kZPBKxDGsTzAaB&uTNFN7_AUPdiFj0j^P|K|@C-@-OFP6+5>ROpDRXO+! zbMUL?&u<>qyV57jQf6c$Yw0*=!8BWe&Bj=>&Gi=C;nO8j#V8{GJN@jRL*$+~Zng`! znJ!kr+&+)rmqJz83>Uob%~;JFxB-YNsnjBj0wGMEcLUawg0b9{Iy+6X2`3eYD~kZ( ztKTb)I9)EW?cVeBx?Vfu?pD3L_bCXMzrMcjGDNGQWa&T@a+h+@5enyp^K3c}N*#(7 zk3Cz@xXDg9B_|akf`T`OG8M!Rd$eyq)@sa%KSZ>esTIT3H_IbV&ZT3^pb7PVHv$P0 ze_vawwODOU_RU!!Twv1ssaVbbUTPUjvqfpSvea4)Ckx@#$^a%IeGa z;cB*eB>1|XY|vBb0foEROq#PPjK2&LeB4_NDa1fB3HAA?O3V8hAeJFEY0^M-NoY=E zn4$}QdmP`cwZl|xytdKHuiwlm*1#Cup4p*eOL;uH z;|6;>F;UN6)_v1V5rWiPlJhpwuEj@iXy~FmGw_bAtKU5m4-rvr@x*hfE>6m-i zq)DQoXOp23+b*G>uGS;&+D3mc8$SU0*xOz$+?L~+e20#6Uotwbtj({(>a;y1X#I-R zndLQcO< zy&gD6R_rSsLhbPnB@3*Z+~}KMwflLy?)CjSKzZ%ufz!P)D?Y(*Btv~$2(Ybk$)R>! zXI1;Oud{Q5SlwO6_{{CiS=9pPVsOQOU2De&yblI5#pWciwd|aE{Wu7F!gN#d1X^0= zkk6%>!@1xL4+b>pW>b+j+T=iV2;RmtPg<`g#vfh1(e3@tDPx3gaOOZ+A38YzB3Hy_ zB@@x-&q{3b47gK{Qa9p08u>jW)B)>F8+en#uOIT21PH`If4q538O}E(X?kf5;3$F1 zjZ9BT$8k<>tImCRsT+}5+hFP<>Mnezr5eLN(Z9EJ^xu7EFZJ&9@$y_=MG{K*IlKgK zOi8Trdb0gRg?e3hfSK0qxq@96&U{SbHwE=nH6w5A9~z5jwtl}E&+e*(GV=oOddBh5 z#-G(|2{^x7%RgRc8mt$O-f2mb&spe4xQtx*hCBOK2|WdwJuK@?Ko+mT&bFdm9-cl{ zwj2k{&*T5b%JEX-e)5v{`r}z>wb)%h_Bnp9%|Qqs_SimziJ34wD*!94v)I&3)&?hb zaVJPcu{UYiX$y%G{QDXkn~Iu8#lkYRy}qA;T6{)|+CAhprAOw|`6lVz=3L@ya7n_~ z;DG$=2KQxl6uy0g_NxmThuyXiJ7bHzWK36jm{fvmJ+2(X&*KXYx@#gvA7cde33dmJ zP$Tiu{ig19t_)BEN{jMKi?GUEjLUdSJ&xu6XqI|;czFB)SBto=yJ%dm=92TfomKq$ zUSxT6+au7kqN*G1z(_rp%O$fG2avQDTrC1;R?$zHAPQCYt_jxLuOoGM-gY@zh6!|$gQs+nJtp<>F1%@>QfX6G$%Y);N##4ud-d;+%K>0 z>u6dJ7j1+1-+0|h{7|B_(P9XhcAt=PH=P`}Fzg(6njvXOS%tK}xA%L-^yVX1L)I3d zIbN1+A-KBVS+cnrchODGvb|}77;Y`K#qR*Vr(rTpsu&6H&FC~2A!VZTkr~sphh#kB z%)N1$9|sU{FPj**-*1;|a`{nmTLMD^+I9O?=;mnjuFsb6I#yG1Ke7}-21qTmQWMn2X?E!0ZURFFi!a9KS!d>dd;x1Czk}9^ok=f>-!vX+0^&I{aJ6* zpyib)f{?AZjg-R+Kb{+Z)Wz?F<^jA!L?Kknh`-{~Rc?i+Vz~BXRetE#eE{Jx4eGZ+ z5JBv{ro-HP4;G7l9E{J`K1+2e!4(?fd%AnHT7h-A3{$QJwqox-KG;)OSzG)3U1C3| zXx15Voe>F%B2VGSs&YA>cfP3|YN;e4$RQ4xP3TSK&y~rAHfoP@S#+yk{_e`TdV|6J zjco5xGcCkb{f{yT9C>tAso1sPp~YC;@C7uN@%~{^U7I2$C8;53w7PX68QP&3;yMUH8HydKC}+9&4%z);&bUQ)<}I#u~r5n z{(}Si@2Tj&UVHWluhtE!w&zDqF30O_WJ;6G-t}Z@WpRE<$aO637ne62^&jl9@fC3_Fw=E{dAb_%>64i+MVFN z+sc>7k^qf{(J!Fl&P;yTA#@=^RCHPe@(;+ zN0)lef{)poCaeQ1;~|_V%V+SA!1aN3S0euq3qk#(1hwsA_2M9xZE{E1;Ml7rcVpsB zQiSGc(JvI+Z+IN>4h|2&_*-=#=J`uL$p>_U?`J+5eI*QuPEGNSdh5D)F}ktg$!act zJo@R<1pNq^J8sEZSaKKt&>`mPUd0pF57l<8=9Sd^)mTBinB-$o3(PzAF;oz;1F{o? zD@&7HN*C-8Um7HKg#hr2ZmjppS*EcwU(t9Ne*J(w|G@&;%$t$8F4k)2f)`ySgo&9hvjut z04rq2^eGA=mLHYv3Gwg>=%R-lAFr7nsZ%(a{kbz02O~_N0SrMLMo^Ax{d{Q{{(HLE zVjVx<+>>>YufL@mXiX!zw@HC1Ld8+AFNVr3a(()(Fw$`J5%A{mf8d%Qf$XcAmP&co zTk=PB8Uqjb4QOhSx`Pq{VQnlT@BO%vbZuse4UQkwgKOoHchSh}L2vS8|KB1es3KBT zjjt$%Bm|eEGr$z4_l{yMDFtTF@j^?eLHVPZ!5c!`8${sQA#TO<~ zHS~fxCV8nbmMwSE$s=~387o(-#h)VtmhW^Y`=*CT19>*Q@WUi;(#n`6MtfW{?fk>B zX-3yF9-~ccVT<(LK1JbPB^Aq0%uA?^ijQ6>r5Rgl=}^Ugc(jAs?$5%HA!Nbk8~5Kp zZK@>Pr)xw!HmmrOjgeut)}`qT0?PB1CzeGFiwwr>EQebOibckGbZ!ZNr{M4~`_1Uu z$?wpS9fJ_jJ?6v0b7*C@9d$J^P&cDo7*sqE;EA3lTW9viBO}KjMgTrF+wUE-;FArL zh@82|Z-|(ZK7WeK$OkE5ZX#rjDhV|OuI-x!nIdJGk9%rB2|WcEYgy1YEv=ZxR-(d$ z8`1D`r~auP)gjTM=I8p7aim?7B5#87yB~*I2j7=)HG-}zN@QHNy|31BNF46BN)k`! z)AQ!690ZpahBK;N+2G6rF!H`Lg>_*8OU*r~0ytuXiFkAcbUOeZipSubs$HLx*{m}kd*9SdMDpA#*#t0TKzaT4;RIvO%ckTb! z)1TSaBuF@<^kRd7iUGES+MZ@TfjdPQ43@#R)$TYgLfj#ANrQB8uJd#ATScq(gMkIo zeH=^#MU{J^+Lpg|&2sR=Mta#`Fynm@3<%D5397JgMt-c|@9s>)OBpp~yV+6+UG0(R zMtK>+R6z|m6`Cq|kK-l`0PVnAi$k8ElpMP0q+&@+?Ipa(?fN{LouIzh&tH7~^>yF? zioZ?BFO`*<0es3aCC&!2IHm}g6Er@*EX($^o;bRK@uGp8wzb@-OXT>#m)4YMu&mt7 zv)N<)XN6z8MltQLKBo?XoMwzDs{sz)?hRbLH~onYvkE-j+~c1;;Ye>OI@3FetCctp z$%k{i8gcB_XE+9&c5;Tgz6#*#+o72C&nRZAVmt$XH>LfN5=sv2M4z`8 ziY+0fT_!+tL z*O4XPGlocvN?QsBXQ(3OM8zI>)=kLs@?i>cxd?CQ==rM}GMiwEl`h7Rd-IZY+)PAW zA2;o`wN}9`t~-!IXT1LC-+LBRS!gls;pue`P2guDQ+=Aj4?`k8$Z;&g%k6-=ZPWO6 z;Bjzq4G-SEuUY;?%(K#V+|$>u zF-u-MX3wE_bF`s+Qu9)~As z1OklD#N(O3(aWMY$G<@mO*<@72ibQ6M zNgIM<(Er zWn5zWmbo;9$xDL}7VHtozdW=FA5xkUI|_;~4^K5%^NhVdTlY)2cDy)FB+nfe>DUd9 zyKRIQ9)TLK^)d1W6#a^f_qk+-lAamOmX>N1$;Z<8RJwNB=vp*Tbbq|UHlJ+EnP{l@ z`Hqzx6+N71nn=!z38wc?aZC&zL%s%BmsXbVnol`>b4MsN$%zWZs;7HM&nQa(o;J-+ zxS!-nV?_4%#uF#Gffa$leKCA+4CSU(@*)@md^yjY><6M#ZWPmUUByEf`m7p@;$xW2 zFB#Sjmm@S*gjp%TL*3@I%M;oPPtT9}Z10Prii`K$Vbm)=92+=uM0nl4f0#7<`F9LH zkUK8^L1dDh#L?rghyAZu`0sE0-`8FVBD>s?f9H7pmGUm_NLh-lFVxU;=_JYeTiyIS z)}ZoW^Ofw6Zywj-(hfsDca)|p7?%LW50etwVabiCbeP%}U$A^>`4hmT>uZwbGC20_ z_ek6`Gr!@c6Rk4j0YC0u?l#Mg?LTYTQV3x`VrlCJ)pY%3fVOAZ5?}KHI&n2ZBgX>` z{)|j!a^`C0l%4(;+zfry=H!%y(?t@{#Y4;OC07GH@8qzz7tGEIaFg@%jP^XwjLH$x zZ#A7ItRfbO$ePXJ>fDb)N-DVu}Wbi-=&^+JOQHm#*1BBhSbb}SKzxW z)|_k|m&B#5q!-FUpU`|#PJZFiD;;b~X}A=YiRmG!MB}Hidg;Z8R80#fviOrc*{Md4 z(Vzim{=(5@aiMx^oCn-r2@TF9+rBs-;v!g;7~_m0JS=+3G`g`(<;mSgCXZ6?FD;YB zFPy}5gas!3Ke2zuhas$SZwm{)Jpb03#%l#$qkTcfh*x7flGUii8r_pBAP_h*e13XH zj;Ah2aTL@`rf?K>#Pa=^^m`5&mOQ;kV|1pt7OtNGbBo zKF|X?C*Z58+FT6#uGdeV zu8^u^Sxdq+BAUHIhrUXl?N@0jN;-Rn^h7LlL?$_;{VG_C&gx+K6_<|(`AJH>POR5K zi9fn?eU!e%MT&VO;FFpvasxOGO7$}(7 z1hyg*8i1|wXh?4=YUoQdu|i9E)9Z40Ahp86Pv<_Gmw!!-*ITfbXzA&QnLzQ+HNoaE zk^IL5nc;g?RW;*#RG#gIFWB)3)@s|o}Yp+VOH&$*#?EK zNMs}Ah${6f&CYrymrScWzNO1|bM0oS4e%PS-}`UMYZOmY2%+@5>a*rNa|n?urKepe z#`H|Qcb#*TI+a#&l3UmW=~PKPKPgh?%OY6@8{&suui#|rI#5@%i^YljAK5GDS&@L} zkXqLr6lm=uY%=wE&F6vepR40v5*))2YAv-0duf!u3@wAcMtOoxbZlAQ-Te7atHy~= z5b2LBB1w4<+H2PvPmryo-;-jJJ}_e8DL=n$z%p@IeY`*dh-z0Ann-od$Xixotl;8o zj)amA{5)-3G^(iIl|sx=jtN{n>wNDf#EONe7#@it6rj%hYiNqS@;gCV-o5;dF_I=5 zaib*_Q8X3NZ;WuHT`9*n{BhB8O|q4G+eo|hwgR2vsy|>iahuv{sXAniEU&;Q>(fG0 zgU%FQ=v0oK(u16Vok`(nAU@0I8JAhi;rhAX8tiO@TM4~JHk~8;yq9r(4&57Gc@!-8 zMKaQ7i+_A22qXc*<)R)Qd}U?j@iLzp{$c`%BtOfKED5sUEQ~bs$CL*Hq{)#5iw+u#~Xs5vbUkrY$}|Ep3-gsIy2x7Ofo_<+z>H^4aj1qx08my(F*!d?E~0 zmRst5U8uFUI#EuZmHA3v7m|USuS@1RgNJorv$Mjg5GyegYyarZ;gNUV3G=&JR6kuL zaHY9`2+#d8J}uhxU@8@=HY&4+)Ro_=~-{_F#jQ?~Poz8ZDDUt$2bDZ_rQ_2S+vdMQ;KknRu2z=-73_w%(qEtDmmsyBuTT z;N#|rf3dzknS)KivZ+jjn_eoJR@_{RWC%dY1Z*YKV z`Gp{$qqxwVU$f3vdqn7Jod(#=ZY!Vg^t!Gn+`DZmXENSq0d5p(T=tebX*!^|KAnHB zzCd=aJSGzz@LPoD)N&16DB;T zfAg05o8Ir5C_%(#^X^Y`Y4kV=iLAN%S^4jzjjv^mSm5YZ!tzc}^hUsUdeP+6fOqIE z9gl`rej@&By;KO`>23DO_eJAbA;yY=n4nRH%}oCqnbN?d+o3yRXH_v`Yi}mB(cw^& zNm@%Lr``fWc|Bi+;|Bc@RRcO$*Nt(5+9o)5gauU`+|FvK7cx$ZY&GQ_HcEQZFTH zM|SDx7%03zw{S@;r1IA4ICl8kY_l2rE!YEuM{SA3q&j1*jK$YCjF39B0U%{-fa_bp zs^=cCb$G^<-rn7bk!*@NZTPFwl*mNma1yRoyEVA_mx||DMam&de)yb1*ttd^wX6uf z7^jX;UF0j5 z0e7;fph)CNLHI>omtPe$zuGQqc8~9B_WePI4|TWW2qcC*7bdnXIb?SrM}Ls{!YH%1 zZmX{_9B$EOYfOcye-KMtg00Y^v@LzGV!2>cjzK8V!*j@usn6bH^JD0q<{<)Ya(elJ z`F2#|*M8eY1Nc64V*)!O%-0v~q!OFEm)pKwI>+or(reQYBmM?{%5tR-RQxx^{Vu*z z^7zBu5`jNhuMR`GzF|aeIrA;18h8?lu;>LO2}0-8PayAGAYpq<>yorC3OC=@fu>rF zi))y3_kxXwL}C$v?UBiQ*55Q#VkLZF!jE|A7n4R#>351IGMzh!{AQIt5cv zS_Wm1mMl7Q((a+7%683V3wh07#ZE-r5mGcNrajc3z82~-5u}Q1d@QI9ZWmRw?DC`kALobe%1Xa zeTZ>sAc;5$H96=xpHAT=0^7*{HB9;&_CE;Sr`>MvXr6CVvj!vUga@>L41)BIg&RH* z4^o+-KA!kx7xDz`IuX087=eE0rKLP5WH zPM|laceT1bWSo0L6**(3jA8O>vzfW7{njdqNC599203rn%F!+a_^Sg;ikC(tDeB$B zH0=c64hl&-_#G`Bv*<^ozIqf1YRn}^K`wmiENiJ(Ks_E^9JQgIY^BYX)+2j;pzX+v z>5@}dN3Fx2mAj*$W>HFBx~$P2EQFRWWq4_G&H{Cto4`M8R1D?VJ#ePE6+sjgP$jibB9{&Mo$vu0v%poqrSK~S(N zz5frL8;S7bZgD4ub6G7RUAc*GBb~d=w#bp^kM|c#^#)yL$1kQWI`11U_^;R8ja31O z=gDEnR&4|;a{I?Z+h&f&8F-8>ib>CM^Ci@G`3L;kpUr|6#F*NVqb#)TitZY{t0e7Z zF^Yi2rfxl*8pq)X#5y+3m^nW8N)?O0Lz z$siMOIK^bIY7rX~GqQ<)CtlM-$dtL<7*EYA-s<*pagNwm#$qMg^51)VJm6j}e1nK1 zRbAxMpt10cK;IgJn;c}=aP2a)4??tj1t~xe=KPx4x9)Y;BmbxPOzaVa<++21*iS}- zLVbJMq)f9{d)_yMnoDp#lLRpf$M!In2mhstWvMY4utMQ`Yc)v9p=(^NApe&j=$|(( zpER$>X*BPTEYf6pxPzaa^Ef5LBx~kj-6)Hp3f#3k^*7?!oh9fVk|ileVWZQQo+LA@ z8c^~r4W}L@nCr6X03L?=rdUEQCsm@~>0*0!(r8wJdph8kGciEOY43M=HF=EmpkTP? zP#~*3lQ_G$M@kBNsr@A>Aj45t+7Gf;gsSg(%ZDQHMrG6PYv63Vh;|wwH^twD0UJ-! zk3y_u*ptG+A?ZMPSvP~l&a^m+XU~P3Z3@PgL2gq10uN8>ih###fC#SpKH6Nur|q~A zVt?c+OK?D_UHx&Va8Sk1QL-~{$7J-WXhD2{&HfN-j#%d+@O};o5T+C4EhpzhT5x6#x=d-RFX(;?abS-2qb_i; zzHd5woCPlXaMgPoLC5PkfjC`+XL?)o;7_9Tg}lsm-H@Sf^je^KFKYm8Nzh@tyQr?} z3obF5=KvO~X(#?dp~Ho_+_~PG*eGj#&}5>05=hzG(2xrcbRhd-fte-b?9?bs0v67V zrQ4HFinrr4V`Et>jCqb9v(=H6zghX)O$Du9AXFS>5>N?Xo^Q(Ns*V_PG2~}0aF# zGKOTk1#U%r&MFc6sQXe?#n)i4yRQVy$HAI=jaxBa_gR$8?>+ z{A(>Svy_rA**_!xUy|sTt0mg}D!P|h09_)N^s+%y zCVUbqpC~k~2f#}Sg#;yhC9Dh1%EV)(#Gw3jA^1+woptYbPIl|&%NIzl{iHr?@UToX zl+S^iPXRvIXm!nBX74*zIt#q7Zol9sBj$jsN)Xjb(T~hqB#AOS*r!S`pan`o?V3+9 z<)+G>LPdnPCMFvyaxOmjktxgr_xSo!qK1^*%NEqx1%t*s5*>z2`O7FTX4dCAx~SSw zfp6tHT;y$~WK24VDeHp<*3R+s)fU_^88?|e)$MgK#aW(63G_CNzpRJV8Zw;E{|v)V zx2P27mgdng zi%DJYqg#K&rBrJA!;|~qq*QPzhK>1N3gRn0JdesT4?t}V{JOLxD{y`ae)Tq!_2{|Jb zFr1C%)<0;U*8#vjEV)ez)p%d9KeKu@X8F03QSiFgU6FgUnRo}XnfZ#~KArwX&u4!< ze4TrRth8Wz-kk-e8hD5w=#PxdwF?32vGbL_M4WUsprAg=tK|36&6?#FHsdyKcyn-; zz$)O}9fp<#J1KQJ`}+=|8{ApZfBWstwqo1BfdYbi*dh35`T8oZIzMN4AI1h1#XH}K zpl&mGJ%N9Rn)D?ub!RFP@!(mz+^a!(UxWqhnHQ_65;zI|>Xk(S`33kaoBv_W39|0~ zx~H*8RD?%CH*?0JXy7YFRVewHim4&NkIDi!ak7fo6>z&^%#zj``x&t7k%Pyz{}|mZ-(Th%9uAXRsGD9Ouc}Un(ahv+;*a7xkkPC;5>hH7b$_wcEnvIpf>k zp)!Dw-mU*no-h`nIMk3HnkU@mW(2qdT}30w65P9Ihj)sHS9{r>xC9!P1Ai*|CYr*Stk9S z7+11ZGQLb2y~vb`*`~ct(BII2Y4AoxeXBs$KS)=8v>qcF;AGS_Av40J=F^8oF!d>- zQq}}gHRZ_F0IxgQBUE>GjE(rL&&Y?5iPY@fVy?<(>7P!r(_auf@L&$44#gMMGu10A zn|}qngr2e;2IJRwfPHJ89YjV&)aG7Z(a@)I01!t8k zzRHzoAUQd)U7oc$Y{wORp98(qBQyYfR)LRQInJ3%rG!^z=Vvm)LECt{Mb7fr;A5Y> z7`%u}u>;>bIRD-^3Wviazz?P@~jcz=L<_WG&^ zy~uq@&MLmI%f>WqS*B9Wv0({$jsqt+;2T{{p_rx1ffWL49$S zK4|^vcOxL{?s~cD^Y4_NVGzRwkYc{~qd6<}CwcL1mjvzaN#Hi}$1I0m?d1NHg0`G0 z8F?D|KCsl%LTE#E^-Hv;e_+Ng^x;jJ^CC2(`P);l-uZ?myKX7$`Qf7^F1+$qeWJl^eg<$PAMqvRforhtIH zux@x0Npgq`a92A0c%AawdKk*-j;ikJyDAtmiuG^nljC(bCgG*y!Ei2BYH$YyBg3+K@RMl@#$V|7hr{1OMQ+i zH)QaFJ=ahTFke|cfN8nBdzXz|t5;k0MQgd}*MJorM*x3IEXhLx_3>Kbj%}?z@%6d2 zVe3~`@rR1!t?insN{o0PPuY`S++ifepOU*vY8AKclr=TO*4Eadyr^>eDytZ!_Vnh$^ZR|!7h}L;b**TY5EaguT#zT`i17}jWmTH$^Ye)40`?| zpTmxfzi~-H=Dx26-LPMZ+@RKB7}uqL3wp1ni9Fbj`R)rZQN3GjgdXCZ!v0W;(Af5D zxZ9}56373Lg9kHi(2OvIDny7ol7ttNPBj%4UY{U~m=Ko|3A?~-5G2MiKl*{{vZL>o zEGV0H0X%oH+t@9!vFj3e_mR zMgLgp3H{z?+csjihGTTK&PX~08o;R|#_~N=V$>Z@fBD^ebB_L8<5cDUol$%)XT6q#DUZRo#h~q)A_1;u9XSZw*4@C+rpxV2y4g6@8D32F+6Xz%w_*X6I=*Gl zr71{BMc@ClaTN{IqsWvDl#*%RNT|+i5M#+{qxL%!(f# z1aa~oE=RvtvVQ=SP;?@MzwiBPYUP=mK6QMke#kE9bddrp8t#_-US?#n@@os8M>h9Q z!)9pBDXi7$$b}|&@-1n;xc>8KQtB}u>+@&rB32a2O!#do%!mXW?F#9h=Fu6zo@GAX@z^uJdKa%_H7#Y)7l8capj zvsvYa_iBnXO1yWI8BY%xVG#*U$i9{65`{OO)PpnP@#wgoVQAi4(7D)oZgGI7HxER@ z_mswGBe@zMj~z~++2Z!tzL!m!?A_|{0?dQL!Zyznpl;6Gcfs7X91d0W(aZJNK+5E1 zR{1UZ$#TP9DtEC^ZRa&}ruikU7ziUTw?7zC{XxA>7*%nz+vir2IQ=P?oIFy*^L_k0 z$Z%IGzUh>L(d&QSLYo0VNUlJ_P{6i}bVB3>WzF-=$D!SX!pupT)s*(D(1ppG z_YUeX;$2CcG0Ku1u}$rRF@f(+bhF>}4m+H`^Hkgq-4;i+BFIdHqc?{!TuO44grovf zS$VmVnpQCMr1GRxwOrM+@}nc7IkkoSvV5!<24g1ayXWudo>eEaD7S?PV^A4<7&pi%A1C?se%`2Wa)zXgE=6a$&@@*m7A*MjnJprPx)K@oJ<+I7?^Q9+4vMf z&3}+5_oADIy|`J{165xz~FDVLP%nh6N z?Zg%*z0OyTpL*K#ecDJWdpFnlXcygr7g2*;?DZ3xQ_rOx)lOHq*F{j6RM2j?`PA)ufANLAf^$}~@9l_0eU zZ5{_#jh5Dy4J0a;#R0CDNNf>e2oEFHLp!eP2ke zTfoZLZA4cP@_78@hJlaRg=1}|C~CFB2jkiN)2X^zSM#;xlI8M_dgip(|I<#3NkHNM z(2Lm@mlq=yP|3}wKEF#U%{Dkb=pz3A=qwUG*zEcq7?=&+LJISNwsd((1yw>rzAZwV z1s{lW^(MTE717DJ$5SsC!xfj^@QNGQd0SF?GPi|t<^e}^$;z~v@n}A{s~Q-ieS0n0 z=e#>*BRN7ZZs!dYfPiPKscFIOBlNg|o&5?E@6SL(vR$It^I)Jat!Fav_@vzCya>lR z_6^}ay69k}g{Sghz2O8sUR?ryL_T;C+g6wMIw>hE{3&vOq1jfa(SGw2I7?yVTZSFO z()WB*MzvC?Bw}*#ki$KO09JFTkIgXMj6{Y_jHV%xbs|*mYmaGD^ITK)ao+aOao(1VTTgz1 zS28-tg4E^4_Tzr4Z1&mFHw&D9!qwP9Zl<_73&?b2K?8~j5x!)~aUObzC#NS$n%H4U zGNk*3jg`{U{klt{Z0QKy6Q17H6&=^J9J!0QZn!Y{eA=pP0&HQ;(Mg75KI6KjTD03) z<&5l=;DI6w)s4{vfq3!{#UWMLn&7;m@1d`D<9=c^{noW-95ibHfaddiq5Fo2rS_L- zEwzV=(^<#5q2Ua}4BM7pVnsF=UvXp)dPjc+w9PP;GBAn;pofJ&vaAbvl$=Z>gheff zVjY%6DqCOgb>=%EY)X&%Ot|mmfIM6o#|JisusZA2NDf6vHdIepOc_gAFb>3kc#hqqvmb2`4(*K`>()i8c#ImI8n?craaY!4=ASb;l7EuQ145Y44 zb*~~cRVjz`+^M}8NmSe2(2}HvY4IP(BJf>%CHPun5W?x3xw#;SJRlk>tuQKIfbP@V zbpmppPHJ_)BW!?_jB9OiK0z3<`&XTMVgRDSWJPO3&F5Gcx4G=7#Jt53$08;e(y>l8vW{~2H+4ci}$p>(+HVKjy3 zv%rKsa%U4o#L*Nk{{pwE&yK+#%lBE&ofm^T#|y4`#SEXoqxTby=7;;wHdMwLw0c2F z-y~ms@3nIo=n(iR?vC_$x=A#=iT*(Q1PcVWuYrL(M&NSlcw|HrXKUC?G?*o zHLt~y?8qXFn2U@IWq(tNsfQ(NHp~~xfCUA}%hAq?*V2b%5;@3TXk>-1jLHL%PZd=FVacV)#Pt$c~4=)3AFg@ zYn188vIOAK*d6AmyMNbhr6VuL{c#Dx&?K?B;Vl@wil^7;AaK$CK&0zCgjqXx_d(C< zvH{_U-=7(Yb%;_vEk@F-O8vujnag6+cc#Mop*BUR=kDcukbrL^0?M}MmTAVkn z#o6l?yM9jZ{*rzeb&fYyY;+b%9+dKddKPEjFuO~)YQJ#E*++B~v(QK^VeLq-9-Fg9 z&Yupqz6M2sh|ggN!}aBGo-n1)NysKu_=e}j`#*$eoabc`g00IDPBSSK1Yc}?u4g1I zmWnYUzGTF865;1hE0^q))RAvfCtmHfQGj7H(%;A6kqdIY4fYyO{sOI`G&MB|{8JC{ zn*nG!MU)m`hhp+lpaG+3!RCpKi7cGFCNw|^;mQ+ro ziHt8hf*2oi4c{9d)LE-2%^paUHZ87v6@b9w;6Ith4qc5pUihlyfpK4=CQ_Z~KpHP| zce;R&Zs3P&8ySU)6kcn1FWGR3_!u*9kgq(^)b&Z%>y5)>Yg=-gHXy~ej|FjGDv;C| zCxI2;=XW2MMb6ty!>JcoP$%BmO;luRn)Y%toyKE}*ZurVKba1Q^iUEV&aS|j~(hGSYWT<#;>L5QGuaT&*S>tTl#i{dKOT<< zCFp1(m7Ho=xUP0-`3?2alrw*xq#>AI;#N`Nrc^+0Q}#fGmrYgAubv8Gd~q{n%Au_q zIlY-Mr0q+oOi0d@xYYRKVU?OaTBQ}~wf|SJQ_&ZQ_R{0NlqW)t&Aubr3ey}=b6Kzl z)GB7m_wC8_M_Vs8lOftsGheodJoD^`r40|!>VXgj+RoShC>*ZuB}(@X-d=Xk9i9So z6%{kqH}XnJGP%a5-yR=-wagUxhRM+*3!ztO6~_UKtPrcLl3>?e4*6R@62cO$lD4fw zfpcHjubYm3X+~iN(A3yc5EFL_pq@UQEtCpMPVJpPY>Y^kTbXBAKzPIX2oRnBI zC1*uAl=*Rm(i>a7Kq28bGG}`nkwRLvepe4wjVnW54__eeVVaOy3}?tA4SY~3 z#Y2AWX(N&q{VnegPzkEEw)JWRrpP+BF1w@>)_J_6G2);X!x}_Q>)O=nV|PA28Xqlo z69y;21%CGcNE~Ef`OuR|e!Y9fV%7o+`@IR{;{4Fyv6&&rnr*B_n2@q}d#ex!b$RbB zLJF29#PJ1bcbS&D^*L|(&jHDmJ>2Ev;|>Sf=DT+-n*lla3r^JBq*>6UBNMC)y6!7Q zTz7@&h85lH))K(XN>VRN^(2@c^EoZIP>KFlC|GTD%mm`#TvFzhc8WAVZ#%{?JM>{9r<1s z&50csky|%g!V23>KW&&2j_v!BY7nYr z$CQoFkJWL}O3nbDCRT>^|LYa@kTqCg(haS z@x*3g;|AJC>cx2Hj1xKV1`{AKC$$NayU5Fez&^3O1$HJ#{Pi>HMj z<_rFiluGzc@2*N8v@OE_U3&j~9sCB`^N)7Adwsl+)dC%;)*?#Ej{0oQk+D~ZBHMVK zRMk2=8Ir^&(kd_bBF7A>PV*y6M*Nf`M@jI^zPI@#U#K1m!&JC$EWiNPQ2X8wVW#TE zhMSrl?v|tA-OwM#Mn&|qP!EC#NIBqz6`$kr91^rl{*Raw~ zLbC?XE_81?XRXxmQEx3%pm|dutt#rgPE7V5&cYV;yuNQueP%I!Mqtoth4jPGq4ZU$ zQ-AaM=E>IXejJI&x&D{LBH(jC5)7p(VuDD4K_6#<^4ZT}=W{kD(%%#ZD{s)LGc*SI zV-GgMz<{Phx|q0Pa*ZXm-Fo_unEF)!%-nB&x`1rZv!2@+B^wj|Nwc3XrAAy2s#_;o z0+9~6{Rg|!`lf&PVOO9sujO0S~a0WaT4qceg+zQhc9DOwzLwj?$ z>mJ1@SjC2Ii|c*^(G%2Oc8^Z{n)un(TbyANSQLeAcoMA*Fe{!S_9cp7K+JLD3-vAE z43I@G*3C#P`IY`e?uJ`S&f{|SyH?W)l%S~_xM1KzvepjpqcK5zR6x6n@|UQnatp}P zgaMuY>tgkw#|rqa(U7dZ~V%yx%=?9Ipp|h-ncBLS7_rNEn^s)i2<)&J#IGP4F&)c`;`004U~S`-g?}e;W#~jOkT#r zB07_D`c1{w(}{ukw#>H8P>}Co4_p^{gmQ1|Iwd~vh~(9~e)lh@K!PSB|wvYRuX>aS|qh;g%eo5=1 zioKo#=ChfS7iIc83G(PegjPPix&I*q#~mXu3`_!YsF|_buNG;4SQC&7CaIb@t!fD! zy14+QkI~eg-c$NI$O&;m3L+!=He( z;tj@i2WuO@8UDU(>Yi|Jo8{W={}O%t>tw&4<8m01O?6%fFlZ}B>NT%me2CQ-nMaoY zlau0gFg2p7I;9xgcm=H$Ccr-?b06>=V1f}okkcoLMIw*>vF3)k_)4OZ(l~0Pl28l zkB)HBuSUtY>nPBKE+hiaTb~*9Ix(_MM}5+H6k`ubij3Z#t(U#0`DfZ)>D#P~8R>2C zWM`z9@2ydK9BN2s^COIyyw8B3t&jfF>2rb&OB7uJgS+KQT0@botR`U)p?<$BaI_l({!D^&&YBfjb?hjugK5*_kLxaj5BTgz6*-XB)XQHp&Y`2DhZH4oPi zhKvAOSbk8KV_FkE#O7~*aT1O6W8pZM0Dio{^9G zoeU}ep^=&=Zf3f_UkVmnz1^>Hp0O%@1>UY9q-=J^wbye1B1@;0Jd4IP`X^|G9BbZ5 zdM1e%ZvNSo{Eyqu-v<|Box=+vG!AS&rq?K_FUI;1`w2E~s# zp^Ch>PiA(Y?CuNv@jf!uVt8Qu_jka>_KNhRo#HyBi!gCq_aj`n=iuSg>y{qrP{dh^)Lh625jR)N=6$ z@0V!T%~NX5cBd?pNX+h+S!zmT6*LmX``lom&>wjM@~X1aJXkHmkLDu-JRYA=Zu}4Uo7xN z%tnhFb$JGcVFGBKSa&Nwzc8p==fJw?^Na+H?t+iX>4dEi^n{H7sV_U-{JI)Gt=S!$ zDVXWdRK$_SCC4q{o)~9!T4iHU^pxUelZ@b*#B~?+^Ldg^b9#lH7L0m(SVbq>?!SY$ zPN78LDuW!~fhBOAmDbYJU}B$h`SWWjXUd*uDkj8K-k;-rBDO+Hw!;NK&zlpEwjE$* z`|ws-!D`@p!$Adp>sQtYF;OC*XP=TYQzJ_fduLX2V#1qWm|tm5NqijNNYx^cqhv?qX1`+Xn;jDcws}79U9sP&Z>Cmj#ZFXr!o4-Gz*W86 z3XQy<77Rdj)!j{fc6`x$_MO?X%2kDH5lF z?C8nfd)ML2$o0XRJx6v&=ig*BBL5@O#>ksW(Y z#HFX_i;h4byTEP^z~Y(q$HpI4i{3?& z;MYrK^FNbq@VEL^raL;ru7|MOR1^$JDUrdC67fzXMPPiB_D*W-l=6GzGRkSI8S@d#MXK_vD^YmwF90m)fDY;UQQ=-``Bm!YDhux#*~21or-KQ=TNy>BT-OvMUML)2T#Q4a%(M zZx-uprR~P{MPkykI*+?}uo+-pQ(!Gn)oN$xitTwgB$d8e((TX&*y)`82{vJR=Iru>sQR#6>g3_8p)-t@f}wqpows@U++!{;%|FKexAW3sk&oLJ0gq5wbX zH+04$;|}P)RT_6A+H-cgUJM-?P6d8Jp*tu~(M2Z!7meRnB<@F){l%d4@`0b&)j^tF z5Zr47p+_2`-zR))UqfEv8@#e(Gp=kJ`ClOz(%u=J$~B>o7%5v52dGYx!1KF=HUzUw zxi*JCxv@8UM5l>4L7pj1rA~bO?4nbHN-90K-O{oR$x^aIeCfTVVMIf@{0}gzuXcFm zC+4_emhAq$KS6AjT3s>*^s-Ce?|!OO0&|M?F}*hT_x4@`e^eK>mh?ayn_U!#grDfs zz_b569}sc_x)3s=&7p}i3eS%O0G9~49$7lyo~UV}mU`=gE3Kd87Vm$a!1-J+XnMHM z>MVOzFwS&~LW}Kfta@eGvL64EF0HJb?PudB7Q~<%CoY!B#ZyNjlN|E4?+SW@K95_8Vaw9_Fb#!otDB&9oOn z+D1nHmhb~&VCRu=Lf1(_0@1pT?Zjye*?;TOV~j81NjKJCLT@g#tO!mI35X&MCvsT3 zY&v`vPJ>yuWg!fB{{r5y-Tl^X9Zd-uv&_}2fWW}sC#9yQTAP3wC*Uee_8CjMRBTv+_zRbM71bi1;4#A^NC%615K2(5ARu>^iWVJX*~Gg-~hPHdkfVeJ0Cse>(iH?1NJdw5m?*1=dO9xS%rTH{dI zrQeTx+qKh|2D6V~{`(bd%rY z&MEeV&;>;x;~S#i{Njr+7n2-ixoVfim^Oed6-#ow8}wYtl!gQ{-DG7!+|MQ-OyQ>k=_uNacJ0C z?%N?+&FvUKOK2l1*QbDXnTXIv9yv%5#s1rMr%>Y_UN;uJD-B(L_}T>+?a{a+-6YG6 z#DxD1f!OE$3m;`D+`f3|p{XS>7>n(xKe%R4&gm@qiq(IpU#OvQP^2G5Fv!wc9!RX) zk9>f_A-^YKOhY%h#8$vW$dhk-x_I=vn~=x-><1GeZ(c?xV503{$mx4zqZ^}6+X72T zW4vrtiTiXmm-&$;j@xdGLkRp_eJ-CF0D+o%U#GY7CnVP5rwlBu<$Mxs+b)dGg*&af zPKY+v&xC-~+*%rJRN3J^hXg4vheRd>>Hw2JGOg+hQcUS#M^vi6Z8wdtYg83_%`$8Q z!2!{bnEOSK-~DjaAmdJq`{Kk=Fr_Dn-I0CfM5gtS2W6SNe^j;nL0YI+96h9CQraY^ zqUyXQ^SZr=pq~;zPQap<*k2NI_S80B(JoC8k%jv@6PU^HXK`+)TnH-#n8$J6Ra6pV zYPoV5UP=EwQ`bMH(o~(gxLkQ5>C{*fH>s*+mCoXPzF=pf#MB0DbaPkck&>`U$#P$^ zhD1d*&(uGnI-_^l4Tg@WgXjwx(R@4BUtR#eA_|L$XAC3mVyxx;QGTq3FNq3h%G&-8 zd@jl7q4!o{UkIbFRzNbZt@UvGP7>9X%9?50<8u7j*mbP;A=r(N);;|GQLp3nq*RC$ zKDYsCl{nmz29O};eTW;A>^ptnhuXrT={|q&H9=bFiU|YdIeL4#1)H0?Eu#Y8IYzQ3 z@Jm1U0tw|qc=P~Rg*C7p2K~WZ(EiND)P9B*?e~t$WyMVIpJupySQK@2T|&HD4xUEN zCDpGmOl$*BhfF`a7OGlct?4~lgN5{rQ)!AUD z5g)2`GXOnk+)yJ~ztN;zyC?O!&{{T~k?lH;CDJ28??%pGHawm%ZEByewDk2pjXKLl zU3PBy>gAlseHEkO5307M6jR-8t&WNy_WuzEwl6s=3hD{CyI$%y{^hIKj)AF(6oRfO zRO-B<6!;C=Ij0?YsOvc|R}VWL_}_A#e~mTbdq`#WQW*JFb+3?G0sONIyQU(z_-Nr(S9-vRc`>CA#mb?(Z7mH*ES@Tntj&|GFC zRp7JQIsNsfF{duVe+Y!0K1BAx&fwz^NtC+3=DvO=O{p0)NBSmku_?qL+3b{jA~TUE zA;^uFBma)pAKMEKYDq}Ir)5>WLJY8Ac+-Q;Nd7Hzuk$_K<07I2>;kyMi>R1Ce8i^O zN{8LuKK2Y35(ySE+Oyt96PW?faHBE#P<~d)$*u{J?!V$X7zG8j}++gD%cFgH>!|-HhjC|OrBG+ zBAj8!wjz}2bOBvcZw%xjzu7G3#{({BnmXQS|CsPfaKBXsnmnF`FE zQ_KRY?VkV;oz$6~Y3nznxuiSaE_i9^!FJ7Z zx-4tOMIo^%TC|wl+SF(udjJFpx|Ela?ZsW*bIs@uEAFdlML5#w%(;oRb+7c0nY-@c z?3kHFrKMrB@joCmssXgqtU8OCUnE-tD3pgtbaQ^HUUdf~cfQO|FoRuo?!A34=bJPe ztezTt?^{7!SEJ+!poPqN?tEVB@KoaQgZ>;D=Hr)od+j;twhdlMfgf*B=P}uTI?M|F z>g@0f=Jdl1$LObznvQRjhM83i0&<20BN?agVu2?a{|%n_SC1XtM527Oq~ix8YDth% zmjn~uyE@+TA1lj?v64zA`|mUEbgVO&2v@f*<(hBh@=VOaCN>$zrvILQUMC66<|OAN z^x(_*d7Q6|?1JM9CfB`B=j?BBJ+}pwp#DR_^z;#ib}UEi%PUucr7=INz)HD${RiWj zz=;gb%bw|yL#pH8^%lLlV_Tv(7OJ0}vPxz8RmrPZOvP`DO10eeJZ%pm4Muqc)l*EabxPBxufri1eET5~v@U_fs=9 zwFOepOoP<^ikEzKw5Uobn-xt(Dzo*BSkq+H;a>mOApWEbd|@{5zmp3|Ck33z9{@;O zU3Wv(iR;Nq0ihnrsn#zcpu=4AyP57nH0<2nR$A|Ej(*o!iuQf61x7` zDd)LOC;^}dFk58s?-Qu1sDU4Jw@Sq|yfw)xdppD9AuFw@vYnS4jQsu~{9<{nS0EKe z`#Z6L%31ZUhKVv{j*OZ4XtO1c(w%JmgZGjTCCC4k8)W*5&7>U&P2>q<-}w+*txPF# zYtqe!yY^j7^RQC1ViCt@D{nOARKL;T(?;UCwW@R$y5f{L?68?!MnD$SMX)5X*I!@; zS?`i+@y@D_-N045ghfXkgx@Fpeqm#Aqy)SDx1Z<)fXV%d(S@Dl+M(A@hHg{6DvV*D5LaisU`I4FCGA z66-Lxp7K9nL*NpvfHfWT3-64Y7qFP}Nn7<;8*hAibTg$3+NSEEIT62Dd54`+TFn?A<{E0hLm#t$sYk#}vdU{N1Y#o^{E&ah^y|`7V`X0hVjbaq>d#rHC zN`iz)g^Y~ztj>DPt@We2qi)x2?aOnq1D_})Tb)pLu)}Sm7i|?j+!rOo4=-Ovx;#7z zvw&q;6aHWCy1azEF8x6dF}+~_g|IpqnA+Ef!o)IoobGYrO#*b!)WYuI^Ssl&cUu!6#W+J&a_5RPY5gQK(~@oi3}aJMp;d~ptVq5PC~+Bk*jxGNB)BIHa@n?fOtS{La=qZ?H;O&kt5?R#;_mv%a0H{a}KBzrzWh z_BzFfbH5K*cW3HnJ11l)j6_F&5-(RsvL`@4Ivs$?p`?*8f8)02vqw)8|6==5J*4%u z1B0X6#{esWRIastllP(v`*4(7M?#iOV1`Blpo9|%HA7){(okKk(6ZRijA{XU_x|vi zHFfpI^_r(KvxaIHzDN24amB%u1p+xOZyF`?uh4j0S~<+k?^YOIn8_Dsq(_≈3LAoSPk5;7H-RZdAQK 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�c~qix+`{H7?pDmSrWRy3 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

  • 2I9os~@M@BLr6UN^#%%TePqnhPn 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

    I3< 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 z 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 %Gh3r-HoCS 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�XuQe;m}Gk@&u!I34QK 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

    *f`L*x$Y;*Rg_t9X@^4 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

    ~~%zZx-;RW?Nk!i&!*{x}L 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ⅈi>wnHOMp+1{t)QPd=8tu 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 z%0D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�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

    >ZO}bL2@TxO;tQ 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

    3^mhXV~Z`$&eaRk{DZr=NJ- z2c^P9TUZysnrAgIMnbtYyrga#(649|0BRcb|~rd_IsUyoEbvgL{9>X8Kw!0_a!)%r8P-2S5uRHifz1 z17O+&T^GfD=WnzCJT|DIXSKON4CMa~+dJdB+9t&c9kz3PN462cI>w0390d%k7Hm${ zW*}SWIe6QLTF!o$tdxP6-AoyaL zRrW{gwQpH*S z-o?n=T4z6HPAx8qdbPp^eBh^L*GevzZ{rUfLeDS&#+IBAe)|AZW*zH&H$l!agD0*0 z_P~w#C6`ENf&x#>arTdgR;^!h6|S~#rl5LGW31kWI)~Jn$5d&l;R&!t#sd5)&U}iNO%h&U=-lTT*2^jOnX)X)D{<2&V>R~bhrYrF0h6%1u*3jg^8$j)r93pwWrHTtbJx>LBX_qhrF z>k{{7pq8)?k^9ewkMjo48?*U?*%9CBOA6ScQtv3!&(f*4S+8wvk`{pg*_(;6(ok>w z7@HMx+q^FqqHT6i_3Ct_UAPn0#3}5KZ|Ov!2Ragkuwr498T{`>`0iEdL=7}lz}ESN z^K%uT@JI6wieS4ExxbnQI;qjb7R#(k2Q<*MlQUiBA8n?tNa@XPUmp>cMTfmhON1~N zqQcg&0~@tTKHR8c6g3?aw+5TH(u6c#^K=M$-GNQ=79al)@|9kh4$$r5$=T%V2nc2<-vd=! ztd?ZbH{eWbh=$MIC`mw1dG7CxQPdI4^pFN&=_0#X@;N4;;tN~xWqjBeB}snZY{pAj z%G9TVvZ~KWMG#er^26Lpm1FCG6Ze9cl)HxgW9Bq;i}o{%q%`edorAMq_wgY>BfVQ9gO#JXvyglDcu znrBa_%}&ZP-SKm&#*HJG>^Ihi;e`1rL>!Wx zvm2LTtn7;on+a2uFV}ux5a&FOKsI0@G+Rt;Z3{JS^cgkY{x&Pc!@;4Vm5u_>VxmpU z-=x?WEYD;ZCo(H;c{p^P6PmftLt~M4#=7o%xMcRhE}_`sd`p7yT5XUYaQ=Mhjyd?% zfG$mA)O?!7w_Ip%|G7$#K4r`533fwZO|kNnRJs*1t zJhW?FKY;V{`NooOr9SySw*Hax=6`4{%iCyVenddSr7KXsenE%r_>Kr^jx2kuksgp8TtU)r!_h7SVT6xJuW9pxN^+UN1FIPiCn`OAo@7-BPX+
    ?tqKtB7~^R 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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/css/styles.css b/static/css/styles.css new file mode 100644 index 0000000..7be499b --- /dev/null +++ b/static/css/styles.css @@ -0,0 +1,190 @@ +@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; + +} + +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/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/kill_house_debt_report.html b/templates/kill_house_debt_report.html new file mode 100644 index 0000000..5b1f177 --- /dev/null +++ b/templates/kill_house_debt_report.html @@ -0,0 +1,174 @@ +{% extends "base.html" %} +{% block title %} +گزارش کشتارگاه و مباشرین با مانده انبار - سامانه رصدیار +{% endblock %} +{% block body %} +
    +
    +
    {{number}}
    +
    {{ report_date }}
    + +
    -
    +
    +
    +

    + گزارش مانده انبار گوشت مرغ کشتارگاه و مباشر +

    + +
    +

    تعداد کل کشتارگاه‌ها: {{ total_count }}

    +

    تاریخ کشتار: {{ production_date }}

    +
    + + + + + + + + + + + + + + + + {% for kill_house in kill_houses %} + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
    ردیفماهیتنام واحد (تلفن)شهروزن کشتار زندهوزن لاشه تولیدیوزن لاشه توزیع شده وزن مانده انبار
    {{ forloop.counter }}{{ kill_house.nature }}{{ kill_house.name_with_phone }}{{ kill_house.city }}{{ kill_house.live_weight }} kg{{ kill_house.carcass_weight }} kg{{ kill_house.distribution_weight }} kg{{ kill_house.remain_weight }} kg
    کشتارگاهی با مانده انبار یافت نشد
    +
    + +
    + +{% if steward_pages %} +{% for steward_page in steward_pages %} +{% if not forloop.first %} +
    +{% endif %} +
    +
    +
    {{number}}
    +
    {{ report_date }}
    +
    -
    +
    +
    +

    + گزارش مانده انبار مباشرین +

    + +
    +

    تعداد مباشرین : {{ steward_count }}

    +

    تاریخ توزیع: {{ yesterday }}

    + {% if steward_pages|length > 1 %} +

    صفحه: {{ forloop.counter }} از {{ steward_pages|length }}

    + {% endif %} +
    + + + + + + + + + + + + + + {% for steward in steward_page %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
    ردیفنام واحدنام و نام خانوادگی (تلفن)وزن ورودیوزن خروجیوزن مانده انبار
    {{ steward.row_number }}{{ steward.unit_name }}{{ steward.name_with_phone }}{{ steward.input_weight }} kg{{ steward.output_weight }} kg{{ steward.remain_weight }} kg
    مباشری با مانده انبار یافت نشد
    +
    + +
    +{% endfor %} +{% endif %} +
    +
    +
    {{number}}
    +
    {{ report_date }}
    + +
    -
    +
    +
    +

    + گزارش کشتارگاه و مباشرین با مانده انبار

    + +
    +

    تعداد کل کشتارگاه‌ها: {{ total_count }}

    +

    تاریخ کشتار: {{ production_date }}

    +
    + + + + + + + + + + + + + + + + {% for kill_house in kill_houses %} + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
    ردیفماهیتنام واحد (تلفن)شهروزن کشتار زندهوزن لاشه تولیدیوزن توزیع لاشهمانده انبار
    {{ forloop.counter }}{{ kill_house.nature }}{{ kill_house.name_with_phone }}{{ kill_house.city }}{{ kill_house.live_weight }} kg{{ kill_house.carcass_weight }} kg{{ kill_house.distribution_weight }} kg{{ kill_house.remain_weight }} kg
    کشتارگاهی با مانده انبار یافت نشد
    +
    + +
    + +{% 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..e59f721 --- /dev/null +++ b/templates/management_all_poultry_and_warehouse.html @@ -0,0 +1,512 @@ +{% 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_quantity_has_quarantine}} (قطعه)

    +

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

    +

    + اختلاف قطعه: + + {{ 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/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..ea2bcc2 --- /dev/null +++ b/ticket/migrations/0001_initial.py @@ -0,0 +1,149 @@ +# Generated by Django 3.2.13 on 2022-12-04 13:13 + +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), + ('authentication', '0001_initial'), + ] + + 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)), + ('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_ticket_ticket_id.py b/ticket/migrations/0002_ticket_ticket_id.py new file mode 100644 index 0000000..f3649de --- /dev/null +++ b/ticket/migrations/0002_ticket_ticket_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2022-12-21 00:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='ticket', + name='ticket_id', + field=models.BigIntegerField(default=0), + ), + ] diff --git a/ticket/migrations/0003_messagesupport_ticketsupport.py b/ticket/migrations/0003_messagesupport_ticketsupport.py new file mode 100644 index 0000000..0db4a3b --- /dev/null +++ b/ticket/migrations/0003_messagesupport_ticketsupport.py @@ -0,0 +1,52 @@ +# Generated by Django 3.2.13 on 2024-06-20 16:09 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0033_auto_20240620_1609'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('ticket', '0002_ticket_ticket_id'), + ] + + 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, 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)), + ('ticket_id', models.BigIntegerField(default=1)), + ('status', 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, + }, + ), + 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)), + ('sender', models.CharField(default='user', max_length=50)), + ('user_location', models.CharField(max_length=250, null=True)), + ('picture', models.CharField(max_length=250, null=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/0004_auto_20241227_1534.py b/ticket/migrations/0004_auto_20241227_1534.py new file mode 100644 index 0000000..f1b151b --- /dev/null +++ b/ticket/migrations/0004_auto_20241227_1534.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2024-12-27 15:34 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0043_auto_20241227_1534'), + ('auth', '0012_alter_user_first_name_max_length'), + ('ticket', '0003_messagesupport_ticketsupport'), + ] + + operations = [ + migrations.RenameField( + model_name='ticketsupport', + old_name='type', + new_name='last_message', + ), + migrations.RemoveField( + model_name='messagesupport', + name='user_location', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='ticket_id', + ), + migrations.AddField( + model_name='messagesupport', + name='last_seen', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='messagesupport', + name='send_message', + field=models.BooleanField(default=False), + ), + 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), + ), + migrations.AddField( + model_name='ticketsupport', + name='role', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='ticketsupport', + name='to_role', + field=models.ManyToManyField(related_name='to_role_ticket', to='auth.Group'), + ), + migrations.AddField( + model_name='ticketsupport', + name='to_user', + field=models.ManyToManyField(related_name='to_user_ticket', to='authentication.SystemUserProfile'), + ), + migrations.AddField( + model_name='ticketsupport', + name='type_ticket', + field=models.CharField(default='single', max_length=100), + ), + 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.AlterField( + model_name='ticketsupport', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.CreateModel( + name='TicketPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('role', models.CharField(max_length=200, null=True)), + ('roles', models.ManyToManyField(related_name='to_role', to='auth.Group')), + ], + ), + ] diff --git a/ticket/migrations/0005_auto_20241228_1050.py b/ticket/migrations/0005_auto_20241228_1050.py new file mode 100644 index 0000000..e795248 --- /dev/null +++ b/ticket/migrations/0005_auto_20241228_1050.py @@ -0,0 +1,50 @@ +# Generated by Django 3.2.13 on 2024-12-28 10:50 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0004_auto_20241227_1534'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketpermission', + name='roles', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='created_by', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='modified_by', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='parent', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='to_role', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='to_user', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='user', + ), + migrations.DeleteModel( + name='MessageSupport', + ), + migrations.DeleteModel( + name='TicketPermission', + ), + migrations.DeleteModel( + name='TicketSupport', + ), + ] diff --git a/ticket/migrations/0006_messagesupport_ticketpermission_ticketsupport.py b/ticket/migrations/0006_messagesupport_ticketpermission_ticketsupport.py new file mode 100644 index 0000000..e0b14b4 --- /dev/null +++ b/ticket/migrations/0006_messagesupport_ticketpermission_ticketsupport.py @@ -0,0 +1,68 @@ +# Generated by Django 3.2.13 on 2024-12-28 10:54 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0044_auto_20241228_1054'), + ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('ticket', '0005_auto_20241228_1050'), + ] + + 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, + }, + ), + migrations.CreateModel( + name='TicketPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('role', models.CharField(max_length=200, null=True)), + ('roles', models.ManyToManyField(related_name='to_role', to='auth.Group')), + ], + ), + 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)), + ('sender', models.CharField(default='user', max_length=50)), + ('picture', models.CharField(max_length=250, null=True)), + ('send_message', models.BooleanField(default=False)), + ('last_seen', models.DateTimeField(null=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(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ticket.ticketsupport')), + ], + ), + ] diff --git a/ticket/migrations/0007_messagesupport_file.py b/ticket/migrations/0007_messagesupport_file.py new file mode 100644 index 0000000..ce02cc5 --- /dev/null +++ b/ticket/migrations/0007_messagesupport_file.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-12-30 11:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0006_messagesupport_ticketpermission_ticketsupport'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='file', + field=models.TextField(null=True), + ), + ] diff --git a/ticket/migrations/0008_auto_20250118_1751.py b/ticket/migrations/0008_auto_20250118_1751.py new file mode 100644 index 0000000..5c3a7b4 --- /dev/null +++ b/ticket/migrations/0008_auto_20250118_1751.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.13 on 2025-01-18 17:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0046_auto_20250118_1751'), + ('ticket', '0007_messagesupport_file'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='read_by', + field=models.ManyToManyField(blank=True, related_name='read_messages', to='authentication.SystemUserProfile'), + ), + migrations.AddField( + model_name='ticketsupport', + name='unread_message', + field=models.BooleanField(default=False), + ), + ] diff --git a/ticket/migrations/0009_auto_20250201_1221.py b/ticket/migrations/0009_auto_20250201_1221.py new file mode 100644 index 0000000..4046c3c --- /dev/null +++ b/ticket/migrations/0009_auto_20250201_1221.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.13 on 2025-02-01 12:21 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0048_auto_20250201_1221'), + ('ticket', '0008_auto_20250118_1751'), + ] + + 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.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/0010_auto_20250525_0951.py b/ticket/migrations/0010_auto_20250525_0951.py new file mode 100644 index 0000000..ae907f0 --- /dev/null +++ b/ticket/migrations/0010_auto_20250525_0951.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.13 on 2025-05-25 09:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0009_auto_20250201_1221'), + ] + + 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)), + ], + ), + migrations.AddField( + model_name='ticketsupport', + name='referred_date', + field=models.DateTimeField(auto_now=True, null=True), + ), + ] 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

    {< zZC}Ico9VkuXV`C?YdFS!zpRM8ptF#4TO8TlVJy+R-a6#-Jl!7vDR?vS)sDb5v*O1J z7j3=TLRboaj!=}`?Ppeid*vBPH)W=F-TGh2NBG@3#f8rdRoA&Y?rdfX-H*9U1RHrN&Nd&m;cd_52PKGTq9C zVqw4D(KeF03cO*Qhcq+8pn$cstEK*_j#8YnPTveEN89!=;{PRv&k@JoQ#f5;_KaP6s6A2X7QbYPkKb=^XYD0 zw-LG@hkwkG4!ID^>5S7NttcoQScdvBm^lP~M08rIA3Agzt-?@b;cs;du00}_ z3F2D~i+h9x2S5_Qi+VHdl-V8&(!j8L^?Nb&M%=~yr<50 z_;v#ZTSIVDA>3O2+h~MNXmH=kKLd#zb@?B$zqC&N64sB79b!l-b*%y__*uVJT} zR?|CN+^oDn0c5)8ASHcE&`|EX0uABTY^8TWcz+qAe}U~1*#C*+jv$qbfgV$uPF`jx zs6zQwgt+w3L`xxceJ5S_#S@|TovvX28nW`zo zTRd-V3NqGSi;N= z(_Azs;FLKgYo;Gg=9H0*j+D!dM?M#=xS|P4*T&GaZP;uumui`@&q|t3Gy!6z>qXf) zpR|=U2XpKa*yMe0r>~{kpuI`Zjj*k|FQMk7ZGqIEHJLi%dCmpv+~su?;Exjv8yc<+WW79`b$=J0 zKHw{ML&**Bny{JntVj#F{Y3C1PHL&osE{C@jSGM@L|yrV8WOxsQNlpW^a2SPe>zNI zel~T6As%c+IY{xleM=ov9$;+3V(DU73|?m&S?*N1v7tmXm!n4<9Ff0NA%weSaCGSJ zjYz08ZNe7vR;VTja_Nl=kp*kIrO?jQNk0pM;8|*28QD%X}T0t>h)eX;0RQjD4R{FdF-dP(`Mg#Vg9qAOxqjxA)l~Mp*77I+Yb`oNS;~btT`OBtNag{ z160d@ocgZDANCI5J)E32r$#&bAjP3K0Gn3+dgs(L$!3C&p?WV2_n8`2%OTI5gaer$ zubw|eFdTJdRdG8s4(9JSuN)v-(vN+GgCdeY2exm2BDK$PS)&5Q}40o1aq{{oxT8s?*wHxc_4C6>mDU?llQlG77 zoXbi&%FTY{k2X>aI^S?4fX5h%qK!K1E54Cc;AS6pES?g~PeNBGs%ot;?N-hImLC-E z!X}Rj%nT!|IcEYIdx#GxG>t6(M3#yl1ihMlLcS+K5S1z(e&4q5`8yYRMbn1kWpfqK zVtpXcZQxBn_PdF(s(Q!L%3XAJ&**|`agF#x9}Xp|pMEy#_S!xFS>BA^B&@XW-eM>x zxyOun9!GBBrM)Tbp#A2pDXb8!DJY;s4%_ykWYg4LZ%{NisYx zWnArD--XYuZUqp!6uA)ZcM`I$07QyE6yzw_@~CGAMCEuI`427j$mb zqPelWepiu3~MxIZe zU%pv(wLKcSqI3(EZiQjH z7d6@41@u4#s{J^gC9L_)*w&lkL6F+Rt7+5Nu^*R8<%ovqBKVEqm=`a6iu)vLSAV-; zA?U)_`)YkWh0g7y_(PZ+BV5+S0FF07T~S$o%)~0#Sjpo%-x@o$j7h0?l=Z`B^_AX> zg}c@{Lq6Y4|6&`1GtoXziRe#uy}(+gwc=gSHVgMX+u)18WbrTX+duP7(H-HjU0!?F z@y8~inN<^^G1A@sapB|lPAv{DbGjrm3UUMw_N?;K;!VkI-Z>MDG`l1AA^1PX&1b=QFSFFf@>d>V-JoB&aXt*Tbl;n*V+Z^x=X``{cq8k7Wrumw7}+YYOZ zDSk5=BARES*?sH2hJd3Mg;Z#TeEHtEG_hoK*iwwO!4g}iOnX>u)9iV>Rdb*-Sd1K^ z{k_zsu7>toI^`pGP1EcSJ6o>J;9(Dex89dN?_B%3#}3Xt8J%BVeVMS#heWp}v1FU( zjw}V?6gNJj37Z4#*%L_AxRw^o6f{wHij&#~2B)J4OjUf=Hv$Pq(#JK6w3mXtBUQTp zqLjbrZ+=w&WD)$nu^?Zo76Ih2BlSnCIYTC6Y(vh|`WZpv#YN$>rW%h8T3t>(jiN^F zZ1b*mHGv4O!Z@@&yS;xZW_(>LveeTFk+%>w!$P7!}Eg;fP0 znOiS(Y@`AkcQxE|iQ&#>?KM!%*u=58Z|)t2dBn!c^Y*AXk~yjC$VE|uSgqG&h0{UD ziPW1xvP09HUy#pPkO3_9=bNIj`%tthqEe*Tm8HLP^}S`Rz@Y zZ@qao;8aPND6D)!vyperzICb+x(?9CS0TyGmtIs5M=-eBa;FF1NPq z;v%8J7SLbfnY#%=O^;zI;ZYcxeCmxr4k5xiW>Ufgv!~D>0^|kn)=yyKuD!YyLi(Q& zA1XRok#WR*CM^YDDdF3j7RwBBmy@d`qjGhl>LqdPbw%7VB21ipSPX-fQ7Tg^1Kkvz zdfK*gh@Ps4s8(9fjt{uN)ST^ZeiCAd!}z^e6L6+o|po{ol<87`)r0p zGq#B9q~vK8MWrWexo1(644^Ss>M7R_X8n0zO2Hh7rwp~6T$4TOI0Uxw>UMQZhg@Gq z_i&xh&gaj5mf9YJtvDVZ*U?mh8lqgRb-JJe14xYP64?4}`ut`BPWq9eWvB7okR3u_ zD~o6udvcHOe`%WpqyJ}~o0sFc3yt3*gYo5Ws*?j=RO8A>=~;-h;j@N@*@FF#xaB_; zYfMX&R9jP;foPYGm1WwO0TRR)pp@mGhtQr^7uA75 z0Yl1aYSlKO9Gtd0!gm+bHvx~AdkmxZ!{c?(9WpENpUsYEcZ+5Gd|Ch)ElWl#H|U>I zMMQh?@<7PebdLH^?Syfdf7?@OYAQ0r9JXGy%_V0>rf2Kw_o=6R9Y?%+PXe z3LY5nRaXr0@-6_*9m3nVQ+2$ac|}~oc=j&9oW1uW-&_A%MoH> zyXVlo{M_yiz8XXnjC3<$-@O!vUL)N}nAD%eU2vQ}KU91J*S4iT;fXbm7Xs52;YypC zMK88s357=HM4QfhDLK}lv1CVvR~1K=GSYmgh1t7=GcsufJ^0|AkkJ z|G3p)X{Z4eCyxY4MYmrbgZ-OB2l2i1yNRyRe5?4jg~Q^M@VPvh;Hdy#RRaS6mw|cU zPz2AO@#=_HrHKJ9*yR@n^YL~GE(~jTxAUt4uLq^qxCAC4cVZeYMEu7M1@haj({1{3 zC7NJ0rpWKYjng7SmR)2PSehm(2X_Gtt*r?C^=5F<{ZCAV45v3=ad{MCb{#o-#R>Q) z8DL59o?ep`?a_FD8BsYcztVoC0diAXh*!nDcqH@^if5>HV6ja3HWh4{sx1wUl{ zF78SUiSvQ1$uL1mb2r`gio70Qid{7-&$abhkE54=cHv?-lK_patC3ia!t%SbwjRah zoab$HM@ofX7G{e|lZ$nre_pAWvM{W8q|3wp0#jI&h0R`mRCp!ed-2kj^cavxHHY61 z!&VQ%6Ms=rqq&nm^YO$Im?%PY7%->wW%#kc+nua^`F$0w+lI?Zf`+sUndVRGHAdx8 zvG@#-Y~0P#W!R-jOIp)P6vIzqm4Xben^cM#lryp20ysX(>k_euY|FbuHF0^weu;ez zVUY)Nz7&qd!&Oh*cFuD5K?rZ$)-UNpi?6@b)687I&3bOBklLrSHZ%Kf*1wusOw4Sv zB71WqbF6~XHy>^Tu)Bq$iQ$xpU0WU3vXI)takV7~MEUL+&D6$K$WNL6uNM9lw5$AQ z8N_?FrYCY)uki3fo6+==rJ8rYB~G~8r?bg?cZt;(!L5jV?xu(#>=F`z9@ZLhz}1G6 zO#=Jm!%WMNtEDy;7-oUS_UPF|BI;oy)fYGw0=RzIF0luiYgv60wb zE#RljBi{A3;?L7K3^54|B;ID>t5u1f0 zM;wprmwO)=ti-jO^zxI9f~iSrGi^0wWq3lK+k_vn!YiaWL@|0WUv77Ej8Sv5p{>95 zs^xgRgT_UIo@CSW%^V|5D<%>^$M+j2HhOEF_>Bc0lPcQT@5dsCZT@heC8kymx4kli zIR<-6#JH2It^}Oi?`4GtU}LVT>m$w&|{>0BP5x>XA7Sa&T>fG~ipn4mLKUlte}t z7H;K_)UjxrcuW5eV_zB7_TFrL+EPJ^J1rC|8iExk6n7}@p}4zCpryDLmmtM0Kyil_ z_uwwYodAKLp>Lma-}~H8XRY%ov(|k4&)S*a-ZOh}{Sq7qdS%$woind3v)uY?&qTRg zv#e_c%2=1)@f}165qWekne>K08v_|bqK%{USSxhC z+la*kEN9I;h-;eeLk+XIm zQhTM>_TFZs!la{!xZ+dY^UCkWmEY6(*gG6KuGs+|{nj^n0YvzF(bDr#QWz%XOMM)~ zR35>b-PgpoKz|$R9%o`C{fMOoQaV#qce!IQdGRt$q1hYf@cfqWp-EaSM|d4epOCpC zhQxRx1!V@|osv?xmUx#OtHJ$3XH!DK`5U=AAbkT(PlT6iY8(p0$f(1|@S2dY<384j zZa!%)u_z7}X5i}6kAG_?RT8aO#MQ6&)AX&c-kKzM$m%MwsqKaG$U^%>B7RPsyAN5g ziQsmS(bR=FzS%+eIAKjmnKKE-)Oc=|V)RG--y;|1dMa3FEWY?s9~$u1MQ>9WgySi9$ox1zB=aQ&=Cu->)k4~VZe`5j-Sf$=9NW<2#?3Ia+>snE&_dEsFAVPCAU&dR+@x?#>Ca*6_rjX5wres(a)8a$dOGe3mYKQb_Dh z>EXy*EaPMB8OeA_K$LvQ;aTY*tlj1^qZn#AYj6qYK~1-N1NHicvFtjbg6j5t6Kdts zKeeI9diY#ZkFAmlI$yded1RS?@_ZhIcZyuQ-Y-Syr#EmiNqV#NM>-^bUlAL$8Qsn^waq}=QYaW)mA z`bUWRzr=6W|2){4)}036QKR~{Uu;%?=A`zwh9?LJA30bPM3jCrp)BuFi)Q#_&QX;k zSt6eK*Lx2NgJ^ggz<6n4&2@@_AeH+4hrN__gM7wT$xPAj0njU>3+ z@`j640_Ev%DqNy8{tCtk3)Eh2M@2(2|+TcFHLHd`7J@;jva1a+I=C8 z3lR~!hm1gjnAsu-GdWN9NxVx_pp{nK0?1%E2MLR}!AVTjGE`3(1j~)_TprnpH9W}MkLwUCocl8Tx#5{2wWOrD zC(~vGph@jNN2c&M+-0ARghu*JTxJ)|!%An414z{_WoT)b=$&rg5h6tw(oEF_b>Kp~ zm&g~>S?N_u7dnxNtXEf+%1gI5-Yn*BtsIEN0!N+$&&vlvu9E79`tXd2_AJC)cjp5k zTbqE}0KWKCfaXK50Pm)JQg{|)Z6Z$X>@rDmU9(|Sy3yMlpohyYOTBKvG=*mtLF)Ir zqky`#*V5{RSALPTXChIrLs0kW*FM@-XwyIlzmfKv$#7SsENIEnIrc7tylo--ry-q?ZM4_IB9SUYi+Vx&WX{^o1Zi z!Ly>bpL~e!rBQ3RtLX5KL0NI)i2O8z2LSt!uIe_UwwToHRi%UN;@q*fOOFLqVWK)q zO!$KOCPj&%2AuDOa!SeLDmR$k1kc-dvswu6g8{qCTZXy~X-Hm85t_iT@0rL{=CykY zndRoG@T<$`T-Y!m*BFB%V?<#3c-dmpq-{WsgTw@&_3T5f1*#r z^5xf0Yb6$!(`3d)8KPG88i*p-{FRJxs=)@x_hs{Z`Ub9tWP*RA+sdx)_H$B$1e*v` z9IjR(Gve~5IXlN|@iLWk{@9o0BrJAEZJrq=H8UBo@yDdAKY`WJngfxn;?Q*z{?a!| zsO#jK+ydsec7p8Ey9eDoJ1Py{?cN{1O)jVh!?;Vw74eq!iAOhvk9*cx?UPHssrQ-m;379T3ho5ax2hYk^Yr*TlQ3Nnc|y;5-BjtbC9>k#&ZY(Y`j+JyT=B=)RFQ zLc_P;!E-||_{efoIAG9$y|1C!*YBq;o=@yZe@meH+0cG&Fcx%B12p|LYi7OplApQ} zW#@@0?TFFQ=B%b(Nl4A6t&@T^X{m!)EUxXCA}12#SW>9+=>(Rb(j_W4Bs&y;Yg1_T z`Dksw%G*M`ahlpDSvWxqo0+8o$DB2LbQo*2MXiJtb~ob}uOfd;?7mN6psA3cGKB5Z zlo@65*BQCZj@%aP_-OL%W_ITd>~y!lPv$!ioJ>zR)-T8zhoq!>Z}rzoe{9$N3#sLF z?QgDt;eydA7CyIq#8F497A|GS9#TFzxb5Uu+OqPB3{tpggZcg8%#aVxQ5#pIR8@zE z^;_!YKzoub+2?Olz5ZMq3>uuDQon~f9d;@m0kvGh3QXtu!%5 z2FJ49B$lt-$r-g@)kwqc8VT~b1DX)&&T=q%qy9bDyqp>>oc=aOo4+*h$Mi`vfX(k^ zSPqjmo~n61wl0iuJujM>N*IdquUdPZ7qOmN}6>?eBn%C=#RJWIs za~1CGfm=1tY>z|iNfQ|WTGaFKeW9!zFQ*x=OFK}deMy~CVVtj)gIA7?MpMMHp1i=C zW_II9Wd;kRP`x7dgZ9WMw06fL-XyVo~Ud|^dBKZ6nRiM+g z)L-_gSOyPN4MyP?Awt=`UJF+u3YS-05BcpaibwY%S4OF=L;-cpir9mrgp#}$KD3p5 z73f6~4+_~urq%3b2kJ6~MVD|FtMlCbxJ6lX`ccqJ2y(rhNDn{2^viG!Qd)w!RZ zn0UD>#pxcn*%~xb@EseK5W!ZV*@uDU!|Q(JeQ#yVjKuO3Y{?OjG&m;R9Z(%o27lQ6 z{p?yXiP;nW(l_H)Kos;W|K9iE|8V9XqX*vq^kC1qI2@@6aN{fLzBFeeIF_Td&8}N8 z0@}jiJ4TC@o%f>=LZjXz2k7;Uo7fL0-*8QCjox%Tnvg8yh_h1@aDnrYEvJ^eKXRfw zbY3qY(zp&ik3~?~wQ6nZIN`=7bW7_oHR9MdKu3n#Ti_8t>;HRH|_l1wRnDzY|z!lMx0amCQNBS zAzg7vR~bS&*CE=PFpva(7OOlaNCrHPkr^pZH>09C#V$+8)lWpbw z+HF5p7Sj|FF=Zv*jaF8vO|}v#3bJZsE1@9uVG8gBT5DA8z(m=YrDVJ;95s#&>SU9S zlKD2JZfL0H%4-;ISh)5V7=i8Ew_d$LMhm~B-{aAwaKNj*@80aX=Czc}D(j_@vpJh+xgKJKX0J~gKd@)OS zV8x1`7T%%iL6PN}H6r1m!eQz-JNrn~E6A!M%Udc{>SAQhl_SHDk2(Ti_bQKUt66Wh ze9>^vi!k>fT3}4yGey34a1m}Hc4GmvkiH}{Ywe$KY?>8}vZi?$6i^^oD>GtQERZy? z+Z{Y`-9Hjg?1+kI0BKSiKJu00t-X7d?FKLGDsLCGJb(#Z=_ha0eShV2`!5E5Po4gD zoaarjPPk@6&hSLq@+bQSx4y5cETciF_S>!6XZ#sf0?SH@n#RBB|9W}KEI=2L3cIK0 zhP>*OxoZziNd8d9Jd||gcpOD(srL9KQ_3H+x2H0S#L}?XztmVu$3aMWTFKdCUp|-j z4S31c?<;U8q{7P1GLjR2ox=0M@9&!HjT%e(tymtZ9YvXYK)75UKfP;ccMQs^(28BQ z5(c7m)={ii?;Z>*U)S;#(@TVHtJa-qc>_xbOoym29R`j{(lF;)%}J`gm1ggWOG0|J$E$?pyxtf z?BMK#pt8Y6hX()!WDWuHJrdJ)(ncFbL`zr)CoE@GGEnVRPGLf|J_aBNpsv0%ed;Kk zfog=PnD(#L2*RC;?X_$swfqR~6*@~ql)$52Z{}a$_f}OfcIiTh;ZCS@=1%w*rZtLR zlfe4U5<{w?RLoqIO?0`+XBh??U3}k)zyj&&k?f*ugzKNHoc)!=5Izb(|O%}M}{GDxPJ!cU1J9U`)9}(ui ziC=MlTSdJg1mQH@JBl%;UiTZForUo0)W=8+Jz%|~p~irGHKeCc8vQD{B&l9N%xGfQ zA7wE@XH@;Zk5iB<#Wz4ZALdv#EN?W>4hL0WAFCJ!y9XXz4|wP$afdP+8y=gHpA7l_ zX$5NVZCH>ohv(t~@3jtV?T?1QT=X_PER@9+w+i}4Uk0%j9KzTI{5})?;*lU9GGv*c zy>A(GZ@#O4lP+7?UVbfaZ7We#rg^iUj5+AWiIyHZT=*zqH4Tfv_y>vqe_6=LmZi7l!ci3PCJxVU~oN<`&@*=5HnQTYQFCN-{NY^EIKV&*%u;m1=lR0kPKuk0yx?(F%n#2Ka> zV-I42x!&qrRASGN?^0_wR}gNLWw$HG@B4p8r%8`$%mM0$Ld^qdh#lNe->l7!cud&K z-i$jCBg#+e+TL7&jwl0LpG9_BI4-dduiXCBZd&a5;+=cy`|C#2a*)6E7%Ci^`H6+6}|N$nj? zRWqeLQ_!!lp+OSKMV z+9A3IO;=*3S@aKOYn|$F)yEdikWAQ9g+7H z=}HDwNFM7d+gI*wS3f3^(oP!MwtsB_BYUgU0T53o_@Y=OV^2j~D8cB}y(8ud6op}N zKXvGxcv`ynA>_h-(2ZITt?1Skktq3NZ^s;MnRB$eyXs08pp6|GlgW7=78}njV7YY8 zXTPwW)!5BJC|dyC%mS=uTR`kVJ@>G=`lkDC;j;pDDW$mlI4QJG`|!or^P2LQz(hNA zMSQD#mw&7X@6L49_UfcaL)Eu|zKaCf%H)W&*S8-Xru}O4Xr=8PmYSK%FU=R~r)Z30 z#?qdsjB!+prf+)H?NgG6tSF}+pj%yBz^}PGUVWX`YcV0oz#KDPka1lmEakPOnV_?ezbyV zw>wWErBki8(*f#sLt%h(d^c62kSexxbDUJzSegwHPFiS0RS!sB9D32Op&k>`_R~?i}8i-y9_tS_v9~ig?7u3+vhd>QOoAhHG=kX1f|b9V9<%bJR4jrk zGv}AmjkYc({n@%3)F9m=&CyO-uUH?~9N3vT$UOvP8KQDRdr?7x^QZ83??}hnM7Gn7 zdyf89in)N1@*9|x>16K8$dQ`JPk&uP@>&}(YXu`)r4Qo4hyqsrXuor?(;^(NW{X%9{^4 z=6CCh)H~;(*rv7AAt^~4Xadt?EhT@FJa@5Qll)F5vAUD}$(wzcu#DlObXBQ#nnk=) z`{~4N%&#%E_LD;vvE?HKjl_7Q8SYd0KytR*bU0EkRe}#w_ln3d$@pMe{(9g-! zjp3xW@hje5>qX(QuU}ra)gO0(Ed051n;0bd)t~!_?ix-@>x{3jrknZ%+;|1fZAD_f z*>bt6;49vDO>MV-1^--ZwdY&^Qhr83XY7J4`A z#}f6Hk1zOh(66A5={0PeTtZ5Oyb+047vU=^!{dMj53<{O`2MA1yjwb%y@Pvhn!bSJ z;L`%cuJmu+t~#g2iuB-Var zAu01AH?IfFu`{WIYQJhZOMjI6(P^GF>UD*O-fUvb@$N36RxVYb?_j(lI5K=Cd@u9B z5_w+wE2ExkDEn~hSn!OC=)~t{pN3$6#b#_-$p^U~-u zs^?e=!`E;-sK9Q)rZZC%L*{67+NHppyiL}Zy#+Z>Lwkqz(W*1fK!X*xYMARI9^*F@ z2-RxB^g$J(v0t7}Ti^Mi6^A#bcS~NnJ9C@Q|BFWd7@QXWZQF?DNyxa2@l9c{0m5v`#=E56u7ENUzGCyld zR*$mRXmt^=r7i&t4sr8perC7`+YxZF$%#SRNTlQ%m0YDOW&tX>46jrUcSR_GA2^Lh1$gJI zzR1-=Pw+WPjZbpd(0nn7=cf;lN!?VS*BX3Fk#qY_;azSLV|mR;jMkCL)3-YEgsOdg zI;*K~17u2H50Ooa%+;mZ(IDUq1oO11cGI865@4%#xPyu1VYzoR-WT^n<~TJ9m%fMw z^bIJ_b!CX?IDPQ|YmtK2579WRu?z^Sb9%7f*_jF7SlyY3C#qiqjW<9QGU6Op3maq< zEp9-Y{Va_ScjxtT3*IV&-t%09CL2p8+Maf8?-v(~j}V7@Tz0*?6+;7{&PX`5*9GbV zq;^bEZ)YFubX?B-Ac#)df;nPTRJ7Y8{QIO3jY;$^Fhq_ZVnWGd>cK?B2kE@HZiwL_ z3ZFX<2oWyp^-}rzPI_G4RVHNvAy#2#*?`wDA$DbfZUp^fVf{DpBM{?nBbJYhKdM2l zok|=ke}xyj_GxQ|-xeNRY@nLb0mz^h0tT+eh8e#d=JB%^Sz7=M8Iqzm_Jy5_7K%ov zyT1zC-~Gmk*YZ!>U@6MI4yZ3&`geQb*AXDUN?f{GXY_R6twdgm1BraUrxpN!gA zB~@mkc@lG%A0#Shy;ZgGex;r|;@j?wszU{4=QAQV4zmq;A8oK|)DH@e=QO>(IO7T4#Sm8GB%w zWmLcv5xUorD~?koK&Z(esZHb*IKKyw*LT`EjAu*i?jAB(8zgGjkt?3-GJKnIq`xPu zjV~5uYNhVmtE9tK88XccnV+%zde>|y!8KlESTuJbzh%#~T!a;qYJo;-uE_Qi%ivr} zw+Dh4{jlPxl@C)9Y*`{)$oUQTkC57Ii4Cf!H7kxyR+yXnp)BjRgEc8pLKM67V!ym^7A^d1O zJg1DZe61@p#b@VZC6o*cl#=}hv)*aipU8+u!v9-5{~Y}0`!s zQ&MT$7&Vt}81w)Geluv@%GPL711SoP5*AFyz!bLB3-9VAygqm9>=-4U-}SZ`;Z{^edHdp{h9H$(Z9i z(eM@z(H)ior1VYoGXAAa zkiJ4)@bV{e=tfVjzGeKIv^4l9qdVKSG$WOgIk5hZ#>DVh^E^gWI$7DEmiEEw_Q_yT zbb}V=@xVl6K;ULNE2G-2Ja&60x~<(lvSE*nKMf*ZG>-h@IWI# ztZ*Kh@Rqq0SLjHnyXFAV>(k`Eifu5%=Xj(C<@Zp%Yv<<)nZ0lRcvvS^yVIeyVFbQ7 z^m=34CE)eutbmnoR=;ET@Vo;rAr|q{n5*03hFtZAa^NV1?UHXU^h^Af@){`LIWx^~ zcYy9&sYp+xH7P^%IoetqEfCX z>XaD#SW!6Q=~^g>KjHRFcA{n1X3;pI$=xT}f%k!4FSGnV8UxuF2FqO*jBhh-T%It| zY)Hq2l4BcL_txcwP3&)&)r!3CtBvy^Hc{VT%BxUgNy5LszGbX2QU~{#!+NLfEZpKq zI=&_55b8MBztx3m8As3d;Y)JcMHjn>(QR8FU?yFgq0 z>7X^Qj(x=wvN(Iy_#;-XVnpj-Dcy|}XQ+LoPdYs`9r3Fp1ms9Gkxe`VvQqLLqh)CG zqV<*JBl7PpCu*6uQtI^=WXS5|gX>gYLcS?`zGc=GnC<-NkO7{6*^vTc<6}t z8LJp81Iq}sB|#G=HOOuBa#eu5uZOp9M=cy4fCmPV@O z&Ot;U$MXoPtH#!Vfef!%w0_2ZqA)_UrT=&f`=Mx<8wFsuQ^e>E(@L`^x-RcH$#co= z*M>>k=p&ILJIdChv1bq_@9r`<>Wor_ev7V5t6oNl0_(NOCd?uhOdw_403Cn6zz6f| z%LA}^tmIV?NqYCBG`?;lV4{$00ZPl}=u%Os`YK(6V&FDQW?6>UM)0uLUjV)@Rs8N) zRp%bccH}Q(w$yiJ5>(AGN^2-w%Rxq0LQ{)8K_g6}68xe4I@uCtEsoO7^wB3T9B_%W zw33aRzKeIX*(tp&CVp9I_<`Z&=BbGTgG+XS_zd_;Nt^0uXV#WoemyRdZE%+jmg~U5 z{CJa+LsnzAESYBP*q?R$+AsJuBY{kmnQ^VyXTCe|Jv(#>R#{fP@La;NXwgkY5r%;O z=`CfsxNa_gaW5SBBIJfHG@VI+$T04`r=8&=g4t_5L&HrO51h^S%Xfcx{JyMOy4JS6 zUJIheC4cVYu`voB{@48yS!eRi<>#M1)FI#AX>M8vk1`8t4UO4Z$TC~!qGLz?#Tedc z>;Jf=%VYS3mL$T4FY|iscktM-zxRC1TzPOaY@a17?JjiG4q}8?9ObGPa8y8LuxV-4 z&uKElzcC+&M)@JjPOjhdS*>|G0-WR(h2`>azTFiYH};?8b=)w!e~?e7!*UDAZcY`f zyrt`ieY&Piv#0I3+F{)B(&(>=)SceQA?rpN2%Fkj>TB_J3*hPnKin&UN(nq58T28f zjz*@(GzNYEVgg*B?;k}G;eTu$8{l~K`<-|)zLi@USxG$zvWLFE?NL0D9nJtiaJ3%^ z9(jFcUE!!u`*jkWrL%3U(`rT%=z($dX~P#|((9-XzV%ADOl8R-fNTcnIrP@-WgKn8 zq0|VaZgUX!qcV{ns(DNS_ru&$;tV@?k45~6r)uaJ_&UwIumpjG*+5@b| zf0k=G)u@5u?22ds**#|?U!MjzLsOD|yORy2F-;98h1(nTup~HiVYM$LFb>_bs|L<& z8e0r7-DJGurephlrT<>3d2F2U2j%`0c44osJwmEy3&}Z}j-S8y#L3lI>EJ&6Ga$7o z>dQj=+U;ft#$keG;}+eAAl2C-vVh2yt&_yc@^f;HoW!!1(0nIdH)H$BR6ZC`i0MGI zsP4U6wy#Haj#2gjBJ_Ro#d5LC;QULo?V?znZRMQsd%@fEs8yENcoGqU$$L(y{!7tH zqO97=6#3b)d+{RUPQoumPOWGg-?W_giw^J29095gJ}3DhzB{D=g?b&e5to;5H9D*m ze5sH9D3?5oE;~|VASyX5eQNI|E{jqr)_-Im-9A0nU4}vFIO`vNNXuCz*WC~SYeCL52{gX&fFT& z?hn2(E(se~t7Dw7NXv7b46Z6d>rR%Em)sU$C~ERtqPVKN|Ib~<7_N=Ez_g3Z*ayMWvW#lvS%{V_pyxrRY7ZGh%A=p|_1N)8sQ8zsu zO@!X^oV;uD5Y=XP_*8bRgs>%uh=7+ZQ-blzRQ92~$xGgz*kpSytK_-NU$O2GMo>o6 zQI12M;IOL@$u*;igYzPu6JmO`WNvcVq(iqN0w!jP?1hS4?(5fDcAS@EGRR-x>WD;1Z1PFv*VN%|y6#hmmN z8|$%t0oJpz)%(m>!IM^jp~+^BePMBk^zs*5Z%PERX$)3Kn`x+s=KLK$7PidDOtmF& zUR7C@hm*(oS93s<9`UAo=;txK_u{itE0 z!6~jNjr{6Mq(@Lbmxp=s0wyh1UU5sDSr*K@{$&i$8dC|!Wq0FZ*bMk`YheNo&-fQ; zcisQDUjk+of38?9S^WVSB82d)h?Y+3t|(y`y))*aHn&`#qFZIFI{ani@IdAG#@(Za zVUfn0dd?#|i~cd!zA9 z?Fe&chv2XT<@0R8XWp|IK671#>HIc7VSx~BH@*#AGIqv|pyC^f z&HTgY-Qs$MR0LUIMDV*Vf0WB84b9LFViL`b`33enKnVh-IAgB-29Ba-Lb%rHXT*J6 z<}}SLwx_g#ox9?3p4HDjn=qMq2!&MEdsx*FGA-SiyAfaAE`YMEIJm6DiY+XUg$#Uj zcRI=kCIbmakd~IfsH$11luq9%bembP(b@~%0EzZzmWIQ|`z;&mI5$xZ?Vud?lNYY)dtD`cin!yrf$`zmDT;Dv301j9i)7w@$#s+a)=> zq64jftl!M~85{#NXi`L-qB#Ra+?G#6lfENqhcz| z=PypN*>c0p9UJq9IUJYOKd^GoW|IlYIaJkXY<)iVTWK2MFi*fU-&D6Aq&*g5hH9a< zbr2VZJj7-z{+Zo=OptN?s;6%)DOiH-YUZ7*Bq^u*jEv|{c6u~JzxCGi4|{2Q#&}Ax z)^bTZz&~++=e9^IbN5=9ZZYjdcIhLzC~c30}Xpbk%=u z=6%_(;ljNE_JOON7@99$RzEn!rr9F6?w&E4f_>V#w9kAN=0k8v!(3rWQlo0DXHy({ z`*vyF_s7zN=#D?5xcb3|B3J3x>Fa_~XZQY+BmU5V=J~n9&>^Yj$nn08gR8WO#>e06 z;IX^QS-(+;==yJA?+Z%2@(wR*uE0YgP;7+8N_{Ucu6EpopiG0+`;4dVlwgtzp1abB zkSlH|WA@1xvhQm;lby;<{YtZyH~)fFKh61jtA=63;rPM&;TyW*%=ysx982-ucuNv|AL3P={O(r0g}`r+qqP-u5Vsj5?C`-< zT%w_EHa2bJksf4lNf*hz*hHjF{;(IPotnq;B#jNN6cPC9?)UPYD#psK;#ej=H=R=z zVvFi21>*x3I#=qftJjq~E&-y_BcgQlqI{ju$`I3~)c1aRT~&I)$nx~I?aanf- zQm#z@_%=*O5z5nEd^~^x6>WOGi%9=M;2iCkUdR^I4HtxQ+}_DZ^+ZX`Ai~&0t#E(h z$D4n?tdS`EkWI~xKoGLFB4jrN9WFqIeii;elcBTaH@-i+sS`1)+ekc`3En4m>@A%R zUm$d@7ESL`I_+}8=BEh1*P+QI$cCXc+?+An>*0D*qL#20j=Q`GJem0sYR=#>Ytl5=X z|7&hY@vt4wKaLua?1zM~V5PpK>B)+*PcLUE@}E6En727h+`Ya|i$Y&)7T@jk!XKvw zS#_r~;+6LqbKIV|E|g})du+O-+vTiu`JgJ&h3CAfjV#d30=4*sflg^BF`Jw6(eC$q zR@{@j*#+BN*gOZ<4i_stuG6>jE1gYF>20NO<~&p;LFyFlLI-}lF(qBM%;T!d8kx}8 z{veWCJ10&*XEmdve{s$4({G%=87&hID^-UV^4R+ApOth!BbkhFB-Y|cHRzn2Zo7^E zvo*LwAOpQP03qnCh`Kc)DYB*RY-_R~pz%m?gVEcpNLh&}VIyF_)7Tr>6PJBu^ht%V z_2^!pnaxJpSgz#5(Fbks2vYK=oO-pZz4#K-BcF6r(W7m|CZr~0`F!e)5=8CynN_7H zg%(EE6l<}mG4cR!9k?4?P})~rHoTDc2J~Wl02X+Dy!^EF z%e6b{l69iNon!41p-}?!Y)?|urtt@4XrI+1S$rl3RS9MqgmsjcO`eyMRF5&>WpZ z^@)nLy{>4{Iex29qwP|^v;pDMC;J2n71H>r=OQjbn>QA9`=jM-{ImyaDWGI&fhfp%cuOut^4a4Ei z?1)$Avi54oord%i;$jGJousi#odgp#qN||wZ{+E@S(~Oqs{B=ust4UecipU7% zY~UWdeuDhti=|DA>MHD=gZ2@tpG~!j?MiI}qQO5?0u_Be527>#sLGG9`*o;0nj|Wv zcc)|Sa!KOBrn`*ZTvXhX`W~%bI*SYP{tSGH*LtSUVYerMQg|0HWG;vzzlY~pHE1gB z(6G-;6rMw=MQYV5Pl0c91}hThDWtNr$?jxa1ZS%c&WR`-tiS5h1se(|92t;uuRlp| zKCe=r*M8S!58W{Jj}(--+fgp$8OYSF2`R!?%K4FHErp*wj>d5TS8!0#RB%9Wt58l- zZI;P`T(%DT+{G??8`ORi_#6NnuG%S74UwrLB-2N)VUyBcEz@|R&W{ajK75(^=FlfO z)g6r_wck}6x_mo_vU-^-#XN*~)*pF_>H3_Dr z*6vnXqd!>j0@^+o6}#=hH^P(HgVisRi&1HfnU#U-O!Jh&j6k19S-_pYTjGXa==q?6WlhAsfF?ktad-EZ3Cx) zWM2X0T_qa`oA8fd!?(z+Xh>s~fsssCyiKQ*zIgv=_H~7FYKo-ml|OWtQ0jRiL~ZU& z`O57Vv9ID#Kp4B#{QVH}73r9r(5JyMjhebHBq^)EXg0;#@$a69Zx+XOoiBYm3x$5X z<#y4EzVrfpagyeax@yPn1BWm;{0oNcUgui+uTMDJSRwF8~N3p>Q(oE=h59pUnaz2k*UWx~Ah|O4L=L_2j$ziaDBd`OfPDwae8LCWPqM zH32gJn^}7JKa~u5x*p|%Jp4@V6-iyT|)OO~r zzjeq-ONAKi~l+J4R{Fq>o2iqfnMpI z)SO<&jBMnII{vKWK2LATV464`9cx3(i4YD(~JEGl9 zBM~(fE(`DR3rp!``DSH}xa<^W6ig#>CK4!mP1#UzNA}|Ip!3kVT3UCm-e&*I+S;nE zAt@5bY8b*GNiTrCU>J)XbAa$PHHe`ukF#yWDme*5k;Ese~MZ*YtR5Xc>- zSf8aTb$9J z^hP|#6^XSC-oL&ZJ8UF5{Bz>&47|)lz_qQD#o&6$_5L-pJ8pw#2UXBS<5BzBc)Nfe zGY;eRJAPDxS{4u|%d6!fJ4#(bCVZkQ*}H&%Xi5vGem5Z1!UE~}_PDP!q#-3{%bnM? zmMW~+L8owR@KX1hD3~w45GwevX*eL%;UUv}HoRzbr^OeTa7_=b@1#?$m+)1ZyFYgO zJgS!2mU!51w-kFbzNpW2IQLUmOC7;TmAc65D#*{ZtD!d*NYOCGja;yzaNbQdg1Z2E zYwU;Rla3M&{L7|n1^{GcbH7zcwB+yo0)LU9?b?P-C%3Wu&edh*vxnEJnrHhxU(7q8 zU)6Mu-`}Mk6N(sY{)Ip0|Mw98>8?kK6{H{qj{7-H82D&0$q2Eu z?Z80^ChMcgjio)6p!pWu0c#7faVB9pS!C9?kkDx(a>fpNe)LlBw}dons6gW+qKv;V z;*V|QzSF^;;)%3sp1?3}bwk$2&)HvI`+ujdTupUps)b?}$}Q}SVzZ5NW>=&%nlY74 zBGvLHhjnzYO=|UiK&T$$DCUTVGd85l@qB3b+%!SWxIf6AMs~3 zV;0;iZ-Nn*R9Eu#@~ju#n^G(zY(++>(yUIZb){g-tB03#gCY>en4X9wT@yO8?zj9A zzGF1kjO&}k#qnfzogeq)hb)yF8nk_kIEbtX9iYtC_@K8n?Ki)y7~fb#!*^>~$cESI zw5oS5Ze%RL4G~hEEdB|yuh_28U*D(AQdomF+{!l+Vp-XtSup3U=_?GoO51y|wm}*{IXLo14K?lR2+(zWUUmDb{D&up?wSTlopv*(KZ3y!O10zQM9Olv*>D_5exN^cqPzB<}CeG&u z|9Qv$8bY0oH`hL5qQYwQ9VPV7f6Gva@t2R$k4(EwJ9;D2Y9A{o;*ZW17NDEl!Wjk? z1CKW+3nK?EqPoLOW+1z1ZrN>Y0IPyllJz<|6r8K)h(rpx6jbF<| z2xw%vDjA;%b`TwV5zd9)^c0oNX0}HB8ak&s(D(Pwnciy_#k%jMp5NTeaBrP0d)K}= ze6+xKY1j@=M80_2P@xd*5Z^)9YP@ym^A_T*pZ{0RdP%gmz*olcLY60 zR+?w-fe!6f%h<5dTNp-c>%8{>NZeYdUci;}Ulhyz|9Gp$d_e`jV$*SgG3zx^J*+G5 zGh@ap8XZ*yBG#63Da^s9hY|w{-E8fF1d7m zRe9e;v(9daSo_DR=2iUb!JfcdqKt(yYzg@qm5WA3%AP{NTENO%wHjXF_+#l7(N3Y` zvT2ui?2pabvz{K|H`%g$K??lgwZ#l}BU3te*K^nBcLdZh0+PcYEbA1s8Q|)20!T;H zu6r#lH8aU(-or@FuTWiZT_*{zx`b#S&F)%r{~V8BeE%5WWpST6?jblrVdYu_JG&my zEcfd**BZNDr??JGkGOReTeT!ZnGM4VE|ET}D*Z#nrer^`LaTT!-PK(tTKVwHD(%um zPhw{E<;u6hmA$1M=o$p4pehjZ;2bD>-R@qbl1%5$$A=dY`2;5melT*W7orVm7&{?) z4{?79s=j-I@ImXqXyB-WR|kC`FRYlpX?Jes`N!>3hf5A48B`k zP$ChY?l0#n(zt(tMZQkFjS>5#wNgcA7l3(;PMC{d)y*$3W}XcCGwp~oi@UK04-~DNj_LWZ0K5>c1r>1QT29{001~Nu^SV=V zd^^r68`jLmuD?1tvaOol*}F>E z!{c^UL;$_K2FI-St2*bO4YjDW5Sjmvv9F41gYA}XDHJQN#c4}%EAGWhad&ruyM{t> zFYXj~4FQ6L;w|nj#hu^;g8aPSI_tkX=X-B*ldG)kwf8);XU}|jTVU-*y>uL8pf6zQ z;iP^PKR>-3=;@%f^{{jNS?hXE)Ot;B;gWR7-TYHixqp*B9T#-JEt~c9%eBSa6C0`p z0?p0eGq=<(Q1Dhrgf<7WA2w4uD|12~dSi}r&x)82=Vg0dM^(FGsA{~Zj2;Pi909_` z*L3E1F8XF^7mv=;cJUm>YOUOAwwK5LCL#j7K2GM{R@mdMZcFC1DJa0*ZhsFPTveL) zG4@Sh@U=a-R&hNxEx!F1ZwNTaf5JsSZ+X9k?jNw27TmHhH`|sDQS#iD59F3LUr&PP z=QJYAT9_Aoegv~Sg*;tDo>K{b4^{YVXdA^2>%L--Pa>JujE}16e zwmwUDT;8dc`$s?jc4w5OPr2-EECB(E0~P{uj{zsYyypH4(-At@Vo@ad-Icy2u(uX; zu*Obh*|aZ|RFLl?0POzulHIxage)Ot@mzc2gZasdtuc=`DN>lrYMSzGe^Q zVl#n13Y5HXLxZLYYNh_HZ?%J&BV4r>*YWOgbme@x7bOPvfSI@S0 zJGZAk)He%VDzL|bs|ba+*JhplALsno5LZ4zMq9{PW@}X<9ivKTu$$60n&@szwd74H z(%91YD~edrJ(VTJEup6@ibq9w4A=Zd&zmQARu9e z5VRfivA^r4YVak!L$Ej$IZlVq-29m!Q9W8T>^y($q}FqJ#|w z^`pSHA(QWMC{st4a1n8#HdX@b~)U*x@7i3LwO|jJ%i&PBvs{7 zOci`0Ym}XQ7VA`}fsrqLRI$)k*INQN4hN7v;Cx$-Z$zl!qxd#?mqyabL-f4U-h{>e zRk|`9GI;%%`ZXp`dLS1zrlESIgL*uK+5UOgjS_ZYcypn-j`)Utk)W+FpXr}|4OaTg z^S(6KTwBj2U;l6a+?kJh@z|X-m$|Y(v8-P|Oy|PiPJez<^verRU%Wdf)c9cMlL~>} zu~So12)NpIDkIEagq0wi2v#BBr}uO`iVcjPceuW_x#3T3xS3?NX$qxgrsdOjtC5eM z6J33FIaN;1zvpiB^mf4QVN&mbFJG6gkekD`%>ZII0=Q!@+(hSaN1&cAog)!k9joyk zPjobf=$_@t^>A@3c#MBplJ`gUIDVWBZv;$Q`%P*Cwbzr9K7hza)z-80R&aLNIN;s5x!eZ}A}^IO@%j(5Lj`&5RZFh%agM7U4NB9nSe$t_afwsRmom9%*3opgoz z3j12YJJq-i4vf1~Xq8FNlnNj3ZrCpqhJxS`;@7U*#&#m}J#B5#k6{nIE5@gJInL*- z^RlrZ;e#;wi$7wq>{StcOD%t3hUKL3z%U27v8vD)W_0CQ`1e6;ekF$}L@N~v+8%?0 zdp{30FA+^f$U{SkVQvMn!@(k#mo794tL-9Lbz%gz@G_<-&bPv>5(6{%E*lz_qYE37 zoPG~83bd)(mg{Z_66j8srevOLc6sf4a+5cIs5`||eu{z93-M8+IdF``Shr;AHbdhM zd?L;5gm_w;yh6PmeC(`+9gw5c3P&!yCe2M}sW&vdJzd4UP#q|FLPSeU%7%7=hOkeWKMq~4nqqH)hS0t&Hja{5RmW{f!6-3 zR@ENW+_X2+%O(nku$tu6UZIELmq*@BFPj_Lj5#>eaISnXpB@LZNK=m0=Vh-+-U zq2XE&_mKUQfDu*=*1SO{xqQE<(duOY)m*lZ+j*OTbzaTAKq4cy{pf1M6ysuYh}0@b z)+@fx7xm&VN_H5D7Th~_J8qM|Xx1O(x-!5&KQ@P5UEdz?d~=>3FK2tLioKzkxq5TB zSdGz{D4L~YO)nx4gK2fg#@^c?`f63orL=u$WOC;^Zn}1$p7Z8VL(Kq7C@tQvZ0n=f zJ`kke-E1s?KO4gZg!}s1JNctoYLi55=>G!P|J9KxCCZ*KnFfE@9r+Dr29JGY52-sa z$k)q3W|_m2yBa%wHX6e>t=xsO`K5sha5RNBLTEd@b`GRo{>fP1)ZO9UQuhbw&!al^ zT&N%4t#zwMm;i63bR1^L>*E6q9RSNX)%KgyN5Xx=wPw1IFGR%*+c*P|2r(bpeJiNH z;1e?;8E3xEf)QEZX>b2qGQhrTZ`#VhYu2NfPkQrSS7K=I{*N~EJdXbPHX#rfBM!*O+g9As+n87_$%0TTS=OlaMUJ%-&j&5>^qbQTcwE=C z1Ar{+N{^3K-=c)3f_7N`QR$}*F(WeXQQVRIa*@sNU>k8tW+S7Lfdf)hyF2 z^+z7IpI)f!l3cz`M3R7LM0T*IJh^#W4}`768iQU|Bmsh`1Wk%PyiSpgN&HO^w`682M%MkFf|At{AI*o&Xob!_X8Iuxp>4D;49L<=**ppAoZn zKMYUOX8q!t#fC_A&VE&vbWflUWJTso-C4@-D1l9ST>%64Tb+)Wf^ zKxJH&XLrsHzsgWPeX6QDYpKpe78$L5GM3_u2>g`f>VMGF>s( zmm}E8mbC*b^Rb+D>K&YHyw~3uuQ6))0}nVaj?o(zux3QP?5$!HU$(lJxHa88f*(tm z$(Wa#g_B#7{j>FJ+Cm644-z03L->J@Rx!0JlLs6bn}4-)Qa!b-5R2b|;s*XBtPz!0 ze%$|4fd9ul{N0HeI)-+us^EgJ7%cN(Xrp&>@4@*_4sLv%uTXh8?(XfASn^Y6 zUtK}+kj}Yzqc5nWeDKCj#Kw{vnA%Eh$YgNbDDiHw6QlFJzQ!qA@w$Vxm?R& zZ5FEvcgRlm-@dHZQYDFKUka1^pgmrPITy&n8Npnhab-y_l&~V=bsnJ2PNfBv?cgBY zs?P6urC&tuW<--D#-+(!%BIo_bf%}~#ct-5*M$l4#WK5#W23IRuQAKg3ml1-oOa@N ztUh1OYqDPaT0LaTqM=&Q^`WTk4$l|4R8&zpTz(|x8@#9~V57(>mj8y9nJ(ZM;Y1}J zMix}WvbghHuh~u7x_?=2L@>HNEKJLMg+aKQ%R@XJQ)OD)tSsx@ardLJ3jR3y9|H$M zqRj_r-X?RAF5IKa?`ow~3MaTFDgr+Mub~Igpo7cuaz|wk!p$YBK1eEB{&Bjo)zJ($ z#P?AM&1%s${Pl#=%%p5KH6JitEwjV-_HRsymW2kpKZ@laeErrzo%NY3^ud` z+DOj?n+;!-GzP5eUV7gu-7;9TBX&FvT({jmochggo6Nb)K*8&l-EsXs`lDu*#j>t0 z%sIxdZE-qm$LP$q-_N?T^%f$t(kzo9#Hc`x*JS*OBqDVdS*T#XwgPatr7 zm1#pdvdXc;!3|S-Oa5>3xT5yOc1J)gbroyks=@@NPggoaHalMd4RS)rZa>J*s#O$v z(q<{%R6$!A!xn_>SMlhWKnS!Y464W5l;oENEllL}D105~Ig@zV728^)V>`OUd7l_F zZ_3g1F=}>9F?GI6PNj1EKzFlbQ=iy(T+?(&d=KBcY7;r-%68NYwPUp!As=G&z7TK ze;nm2phjIRs3jNC)3X>=a#KcRp6p+-mM4|ozVkPWCuA+$LJm*X`WRnGSi7tiXInY7 znv(BBp5jrxlE6)i5*7$c6lb%*1&B3V`=<4mY+Oiw( zwf)w-$=DGJ7tz9Ss`pub&e5foVVipE_bgXXVjma)YVQKDuPhyPJ7QK?^+PX$zToRg z)E97FpDrV6>}rRigr*8&9}w3wUM-{1V?M2b-3%|E{88nAle=l)0O5XS&!-!F!`&A` zO6J0S`$Iv0wxfVGZW{9+ME4qG^qmGjjzzK4ruDZ>R*!4)CQH$d?9PBoy8A_I-8CCS zdLPr9L0_($Duktm>;UDhLuVQDXZcUP`l|^;eHI2_?Y;%MB6_>$2Lf(9m4B!j4ezvv z=90z2NIP*cP_{BZWD4~4nJ>wZQ zy53|?>zk$(x|sWVAKctFMN!^>&uLEjp0X=IFU!((n7yg|b`aXAB$xK{FXZ>kos8WU z90G;Y<`}DP?2KTrJIuc1%^jO~8!ut+gIB-o(x-?X9cO(#I%IIOZb*M}D>KJ*pfN%* z9!YcOQ)j)4!PMz_q8na@8WrGjl4C`KK^&_)NRko@ztt#Z66^FrO4L6(zP8;dn#go# z`2n(X3VB>JQ?njeJL!R?2W=OUBhHd}*>7Ql(Y_(gD^=4wbaqEWZMb-FYx^$#$g* zsA<0cphn+3oM;vM`Y=7CfF-4FW+r!sb1g5Y*rJrYSgGt;`?Vx4bS)wErlHW0lbEp2 zr8vp?C*4GW9|UjI*G1JzyqI3U2Q(#w85xsvrFV+E6ZL40qA?eJZ3cA*G1 zY>IqX(H3XIn*2Q34I7ADtjsF%?aDFybLh4vRV??`EBVzBCzlxD+&0*w&=TefT#YIW z)95ZTw*F>*;-50a?9Vf+E4XBHr}Avq);SAvWh?ieGGm>)E~sYf9n6ll zF6Y}8D?p!B#|ls%i1HoVoH&+eP->AiGGy#g5Q_Wbwl*EGrLda9i9UJ^j)Qu461W^6 zTI)i&(Fgd@&-O=uV|u{Wnw{d+{d^5`B^r6af=yDL5=yM(*0JmusVo^{`I*4Oz|Iynk zkAmlOU6BWh&}KpGQD~a;-bv%GFMJ;|i->+a3-dlwaB1tnPhu2Fr>34}JoRjAbftU* z;NEx#JO$o1h!~ms?)UBy^Xf<&8>KYQc1UEbn})H-7;^1#@=jy2!@C)ZRCTH9MemM~ z4W{+KUV}cVKTxa*_$?i58l={nDQ1YQDg(OP$(u>P|4w=x2AKTStYg+W)m zFxM1+_ko70c(Qhe9|jT=tuPv1YtWWS)R?%Xd-f^n{i>g~^wIFr&rd(1ia_k*_;U?| zl(6gZVyAM;L)JSpUGCjvwY)Tg;g^{QqvuA;N96?a-M!7W=QQ`T$5hbnbK8yv^EiVI z8VSM^QpAzS1-@u49PQdPgTKI%DwKJkB>}z@YJ< z5-ZJl!KkhD7}eMfHao}-2Z+`EAYG|xYddtc+MZ(#*}3_y`TFs?U3!eBa;Zc6<`7Nh zQwryeywM59{|=Y_KRSOx{s%Upnx1lr2DS?Wiy*}vMhg%t+?{WHqf}o?LYVI_99Xr3 zHa^QI{+!_WvT4#W|B@Tm*9LlQ*&U6;U4rfQa&B!T^`W?0rDYKyZh;rmT3+(hRJ%kU zOMF2PM%+;MP3{WsSw%b1`}>}Z?a{A3nI=qak6^lRqmR8HOMuu(mn?~Q*vQRmKNq%b zelEmyh_oq#%w9OSdT2luP}8GdporrUT#dU z*(KI*G!NEVs;eeva=+u%mnt`yU_L1^Ne%UE*i)LJb}6u43eHQi#w)N7oEw3$j`}nM z)tlfTAFN9It*$Fq5s%w7Ps6FYX2!)Zs<@VCiFU!Z<7Y2{Xl$}7L>o%^hMCx%#RH62 zqVlAT8PkbLoSnT<^Olcl&y7vjVdU;Tb-=dVTI$SFpXAdO`R%>8z|Pr@zR>M3*YoUDhz-<4Z8*6d2kx6kLg>JGDn3TKB`0t3+9Kp=~` zp9Y7o!S1Gf9@X|)U8q+AEuw#ge~$GH@=n7v0b=B4HAp^3R7JlLd@V5>evL-H~M(=No$eiA^oP0TFN{wAYFnq-ymN$p#}(W0-H3Rb{U>=P%MoSb_zy% zzL9<SYby%QkF0Kha?FIUo-Eu_C;Cg7+Y5e&9cobWy#xQsBla+Bo64J-_D~hx z(u?|3^Xeo=d}OebuEwRKjE=_W8F4QF{nx`DWCN<-osG6*KTL3;)W2=i9>}ZWEg@a$DAs*HUc`~dF?+|| z(Dr!0?-hGAcMyGN4H&PQFZ?<*izrdc1#l>v@#R<^x&;9wOsg6abE4gy1%RY$5)^Xt z^h`^e8DKlX1iD$BECjS#m&2&DcC5bbPVY%Y8>ibA3|})fOg`MVztQll2~YPjBQNzg znOSh@ObHOJJNG$)$tBxkvYFl5(TgD3Hec*aZcxNieu%M*%RzVvvx@F64{whxD+G^S z*a`#O5l(0BzMg>(V6Q*it8Lz<YwTuXncZ_F0bgxX;Yhh_lZ?yGz}l zw1x^zO>--96e>%!*dF>N{>=)8Jpc49tr#|C;tSO`rqGqn&Cq>5BpfYKA1H%Ec~ke8 zVSg0nHsYcYpADRLTzN4{Rv9>0eb(SKlLhcd6SvoXgJR^nGkmjYJfx0%mP*^&U_q~; z&E8G~aa^d4zBW}!avru@mg_w7BFnQ<4XvfO%M?na>hn$?a~~TceDxxTAq(l#C&aOz zAuCFm&(4TOK}FOdQXCe`*8mQKH{bPPw97l=WYBD;&lRHv#d#MpRRcUa!nwiJwu~Aq zrk|_ll8Jy_^B!(m(Nct#*rS#&S(!Vp1aMtSxj3mo_0)XTsQgSI1*3_*FTzWn5}pUTWSt!rBgB)v<1Kcs`T27~BtJC@YvvU38|JG0M;RhuRUDk-UY{dKN45+uJ; zOJgv%?izW42YjL;*?|6EDGsX#HQse!&86Z1&MX!JnSb@|+7^ah>gc-}AR{1}7*>@HT^|{3IX5ax_N`i3 zNbHaP|Iqv2=i+_VKfpXss^w*DT29)xmxK>OnVpLmoo87K#7EBuG>W#%bUmbHi#N`6`D@HFTm5ZakcCBHb&HOC)mi@bLmp*xLk`MWA*gI&Z2WZ8@bPANp$5QLl9 zF7X)oLiS($PNQ&;c2$B`OMeYO%d}~P#EV)9v)=C|YWfxBVd#VRYs}uEO}t%jfhK2* z;zv(2-*@WYs}(KjnSvT-dkPhO@C(=^K7*`nz^}I3s&>e{?R2Ugj+x zynWN2og2e=;M)694MYaaV;_*!4e~Bu_AftM2mktfp#x-&_!zBw1^T*ZV-3}c}1#T=| zZx-&2;3v<=53W;u;wxw%$%WeNj5Jb&1`dB_ctry4nii>?X>noc{h-zcKMVdg_6ow=X_W1|kNBlz^a@UBguV03mJ`{EpAil)N z(()BLM7|UBP&;#&5wc+A3ErHS=^Ela@ysp_b88N`0gpA^8yrYdQdHLUn>fbRO7oil)_;U322OOy_D1Rw2)-MbRswizKemmkcJ?1u6!HiaBn+lg#X*(FwOL zK56ei$e=Fi`scD93 zEuy(EvDjShL)~L&)?_F9zTsl6tb7Er^|){DBVhlyPhEum-x+{}PKy65^B7?IfrdaQ z_6+OTH%YsGOZAG4+WN#^=*HCcDRUjNV!2xaY_`}#p4BQW{8wVBZDP|BLJZEu);HPC z!F@PP;{39|YWccNQV*;e3DH!oyY&5RKQ8pRTsS3`(^?d#MZ{~qZmSKiA-l6P;zv5P zE3;5Ckumtrkf4INHAC6&@tPZSXG(+UkwsBv#$;Ud>AykxcoEsXSnl6w?q0eXSJrgc>}s>x zZ{KP;qrYtwLm4$&85GqE_?=yOoXKCInq$$(kyXxDEfKNL+Tu1d5yacMGlTi3eP27R z_yHam%+ypsql7AS>yl4Qj^6Hv@6oVBhjF6;S(_AG0H27$SvI9+TuCJPuu)?Z$lDem zorqh_i8}fM)}gUw4Ql$XxzMq6F&0WBWdhJjof}>TohgPyxtl`G43cCVlHAI_}mwL7|;#6Rh>y9rZ0AR+C>_Q2;LD=OetQ{C!65`M@11@Qi&%@!ukv{JiQRA1r z;SCe3JguRCj?cNV^{w=7H64Jr`S5*>ZOpe*QgH>=kN^S4L>Ja}yzI7KQd7M_5#%9W zm^yI!Z!JXuDh1phM|jiq$L(55oUt%h$A)G@!{wh1WpzH(C1W=MJ8HQBXl>oB#JRf% z!0R5{X=Q)(*#yI&9kx#+z})B6_ZW-7`xiJo@Wp@n(R|v&1IQ)PZ`tSM14bjzKbh%*Fw(QR1sR6bJLE%*^@` z-C-jL(_;4@$IE1B3{e~#GJVXN6u#4@JvfR?s-R;L@7H765h>pf28_w6t&BbGE2w{e z#VQ(?izowm*&u!qCb#q+)Wy4eQSQN!<|gx6o1rKFEl-x)xqfY!_FF3@K1tvzIFN0( z+Bap1sl2S$lV}Hmk#4rF-?ZIZ_@UM_RBkcu&0IJe90mt!@(F!UF36^ zXSFQXY~aNy5PngE3JHbnwB3DJ z2iGeY9E}_RmTFO~N_|+(w_~V`80JsXyY&Rert(LJofe#g7PC@U(E@Vf*sKe1Otl-b zN!s&D>-P~i{k5&jKCr_@J#)QYJ&K;BYAyci)5+GZjBcH4Zm-lE{;3q%5AA+DRh1u3 z{91yRmh`X*KNz^wuSRBXFfBd+SvvFA2CA8$nm@n-`yaj^l84!eSek#r{o`MH+w@wg8h6Ncz= zKr55oDqa~P^XzpjTu6DE?PAjPS9(3aQB)Ic)a|Bn($wbJ8KqvcamMvn-g!-%-zydU zx*y;eJM`@UO~k%g{uP++38)Y;qk$$$Isft|7hEZ`!#&v_f|*H@+EuIPU{KUlG0slu zZ<$Za&6>i$zWw3o!z0WR4#CdN*_Fsg%Zc^%blKrGCX+WxaRDM3{hybK-I*x*D8 z_?)HViKU#ev|GC9Nqm1^dEhvQ$?K4J(JR%F?Xac>J-$mioQ2B2Un)Gw5%4Q-yjych ztRez1-~NiLoj&t0q z@Y6Cfouv0RSpkyi*3ByFv@>D(L*-Y+1L=@iZWL{!Yk3@RW6q&+Xj)B4k8cdr50AkQ z7tcTHbeVW3yw!nu$#(%`{uU77H(+nRGpuWc`E1nNFgUWNdGhqox!b8>sH^Q&)qFxB z6tBlT@W<%A{IHsTjp}{Jq9Yk@jE4t-^^9Oe_e|7-N@dIeFa!vV2lG|s>#pphU=lE$ zH*8spiVKJG%{Tf9ULZpic3+25p!s-a$NdcWW9!Wnl|jvQrP$=RGL@>YSV`2UJwGBq z(3#ZB#rJQz)XRUm)YHpieyOWRFjzm}*Bt0TTemI1hgq{~OmGHO)S1Ibf_>?mvA54d z$Aig8B4iHuy##4mUyTx~;`3uIy4_wn4$g+{+in;C30v10sgpgH<7&(xW3XAqo5rVk z=VALrzd#7)!-~O7CK`=5549H?!{Q(YHUlTf3}5qWzi?YreW#95nuUzbs}HWr8jB~N z50~uCJLgsN!##Zaw`_Cxo(W?A=u9eFqiE$x#?{}KU_ElC_`|uuc*7qeDRc26H%uc3 zRYu5_sv(0v>qXMQUP9U@FUq8>`?D-jQCfdOh`w$^#~X9YwMvNu@Q;OmSSsn&a`Uz! zvK{0Y6=nl&%z4dNcCt`~R#QK$b6=L1-NNUWn&|#+g=Rn6HF}ggPGFpYq5a3LH6NaZ zC|P}nZ|->9o&^0U9?A=rJHKfHg!GTy#2IyyVhZYXcB5@5t$m&k5?0x(nWm62KZ*|M zB)#8k93+1l{P^%_zfcv{w7Gnc?&R-eNyTukCB8hXTo5*sIqL}3JHjVCoc%%wsJiFB z)x)fnqs4!l1ZUxsGFH!hjW}%``qAkUh{X#X6<6|pgE`u9s8+QI84bU_Xw40PD2@^x ziY%xlc@>6H;`#(^rSM&>DdH~vXe^}k95Cx(&6hmBkXjgh#4cZGCJH`Yc@yzWpVcwC zSZ(7|wO=HfxfL(KflYW%kGc@O4rOhohVD=H@5AK279Zaj@qwJFZUYttVspFT2dFRq z`}!C6eC$7ZU14zgXJ15Qxyxw z`oeh4AG5qqWSyG~!Gm|O$7Ba5|taoY{k`Yl^0>v4$&Mn)`8zvyZc|L2}` zS*(X&b<<57HkPlSJ&r-#fk6V)v^L9igK>r1q<176&S0XL=>X>r0Wl3XhfNdqyi2%=Bbs(%*Ao32UJ(`g(lkA^fXxG14`70MZ<)B1D--f z#bQrJDUGVes8GV8J;U+MiVk_2j&n%Cg6I9^9bPaygzI$qCqFS>$fFNdU~He90+w|C z{r#~udppx{0Z!=+_|Tm0&F%)S_`suMs;gIPU2i7q8Gwnk;TB^P`WOkBZCL0{^G0MwvU6}PI z0WREBucWF?VxQ7HnUR2#8PFX+cf5_3GWZ#$jNRSf5nzD9|v0-R#0h@ZWq@?_zL^ClN!v+40c&tQG z8NHGw{hk~Aoo_1hVA@`uKq@DETS~F984p?UNWN;l%Kg>c8V*%ODCR}J(h)a?(QiVX z-v#_Br+tZvr<9$r%OTU@{=Ua>>|-B6(&+f((_iRheK8DZ3M(=yhFR|CPPI&&%QDT*z}eGB;Ms8c3;F>36cCUPrKWfIM-XEP|+NK!hL8A`Zw# zc@4f!S!~Y3x&4?*)E>%p?ko;(gq?PdpaTfQVUNCc%q~>E)N8i(B@Vx4p|`vSi@=7& zxvN5e*HD_nO=(wI{XwYP`AjJQHq}6&!30HqjcA6{O~>?#KtcAC2AKJX~swc~qgt zXHZl1N-G?C57e*9Yo+NZ(=q8(_uH*rG%pV<+HqTn&-6-6Td^0!uVn}U{743kpoW-E zyY2>}l9#>o2v8#dsqv!;vGp%$E z4a@u8`=4hotb9Bd%esS^ihm^mF7$AS+mlwU{H+8AGzyR2G0b=KToBhyOResNJr>qE5UWMw6|6Uh zuHlC)xeh?ze<0bk0i!KJV@WCQavaMvi+)d>P8J!dn^yBwvR2J8a##*{@zis@TNOHxge;GA80 z?m|y%_+ghCZ@t;}Tpr(UFQ>Qu%?Nha63EPo8u>RWgrWba5TtPlgGy^tNTK5N0nUc~ zTI3`v14$=4aNN2xWia6nHJ_WRp2gj!#ei5X?WyRcr+50(a^E{8?}rf^)m4}m@_k4~ zXoHYsHmcQrHK)9x20e@*8*KzJWxDwf4@?D7d|CPSGy*u5!3?NbF){Nwz|2*uoO{EO;FvapI8jf?ULcX_N z>1$;$ZgPj3G}%NS(_$4^scT?_g3Z#k&J0AF|NboT2$i53sp3Wq+hQIyl-kh>ezIoS zVw({)Yxo)ETmOaO1{Iy7aV7pfDdFdhti|qKNB#;D&vjj=(=})B!PKBFdPvO{=a4k) zQ>UAc&s;xw(~!!-HDBy@>o;v!xc(Sh?OJCCOBI77TMnT$00ry{wJ28xZ+LfHb`m2>Fp;-o)1v-kZ$7u(#hf?c@+XYsp z#w(L{weR_Lv0rI_{hbjI#izq0ZH(UGAx4vUYYoV|Bk*-r3(?u+0z5ACU1}lGGlKql zNqULe9DZ1QsVtZ!{Vg?-rG%}@y{``DKnWXpMOZM!7=X_zEl#9J>HFTep_8OIk4b9- z81k=0H86_P1F2a#%=0ZNtc{@eIe4Ynie$fyq5EncI za#G!rU6J&`rk{fbs@MgvhDY~_GWphnT2hgv`iunWC!=op^QwSzvPD#jq%(>b6WyI* zts)+5l+ieIM8$DEQt;PA4;r}l1FJ1(d7tcs9}nLCOUrEbH!q641SJ#TjHnvazv z;@y(QUcHVyTP#;O#v9FMboCNR+jkm>=AC0F;?hB z<4M!Xu%z&RpMN3u+CTrWX%;)cg`$jB zlxjDNmQ)ojjE+0NdA8E4-sh9d?_DT z2$%A<&$*cMbiK6@ML0m)Yl7FD(9YSP!dKT^4K#!`>_hd7TkZY6aSH`8#y*A5$_a}a zbEgj{LFZ(K0o;tr{G6xPv$J)LCmunqiRQnC|* zmHr{K&i(G3v}CN;xh4Wzh3V8c5)T`5WNx;G2iNYT zuJA3;Jk=7ykT7JZ?fXj5_SDh?Ww0Xzkx=;G`7Vh^x&K`BnXOKxdJ6>@=g9nt^wIV; zBE@l~J1uYdl*_|BdjY}~Z`tY;&K-OH2jGXRPF2KdcjCRh*r|;;Z9@B3t-3)6-$0ldOMFe<`ZBVU<5>e|^s5{%fp^;^UyUFHdu6jb>cG zZ2phx{PRvYSgoxOHT{Yx%^l$bLKO53w|X&YG#`{G9q7@MUY|56 zQ6&_VN5zMNJxRJ|E;F90qbC;KA|K4mId)+5QlEmk8I@dnDqJ15vs&*EH1`Ps5)1cS z`dQ{rnm7GsNEO$S^Rrl*0a>m6fPnd!YxziC$@M_7tN@n7?ymLYYgEC?x%R&XS`H%(HR~HQkpKo0 zyV;)ZRIvVo@IoI{4?8x!N}FOW&cEV~JT@2P{f4CGCBON_>{C;02z&cbV90uI2nxIn@nyel_KvHHA|I4V$Rr z41!h947G24kNnQKxte6oB})P?xbA`0Bbj3;yT4fb-LR4{gI zE!x}{v6kDR9Vbn9Wk4f7>0zy^+vdsFsTY9R{^@kTT{2}}fAVIhB}sjpW}3+6@_4|b zW?qMSpT&uGEqXWU5UPkJ+mJHn=XKK~b-Gy(UH6r`6t${7ZHht>A+lLH;?P_7@CCz( z4O;KIkKAm6-mgKAk?DAkSxWBRELOA)(|}o%4&Ts|W(J9Up_M7U*b%G z$nE*)pqO`#s!|RPXX5D30XewWe>h{W%_3W1-0#I)2hKc9|8!7`L!}nB=u8c3>iS?^ z1tjt3q2{E(Il?bo6W5e37Z9^~1OF4YSnq#;G;>MdHp5rir zu}#%o#(Tr1y}5wPk=nHR>py%|wO2mcYYWlaYx(gW%L`gPk7&Db8l@TO8OjQ-z`HA+ zn@+38X}U(9<8=Wl=G^`-rg`5PK8F`MH~4FK%5A1WP`7r=#vuNxKdiDA0PI`U!k(Eq zhPA)a>cDnnv0ob zoyiW5iC3+A4wd}Vy$v)f-@d-oi*~TNkJ)rCI4x`$SS zJc}1@k6p*oyBAkl&F;y&b!K83N`ioqcA?K$J*6?QCf>_S3$WX0D)oY9l?w?*;Z;6%EFj%hFd z*6C+8eGsGu*S!%P@#gSY1t@%Q3;5MN>SjL$kgG((tPH)bkl^8WlCH=^$9ip_JjBvT+p9e4nvdM7X6pWjGce`GK~sEzj7k!A--6TC-PLteZ^pm443C#K{SQcq&M< zW@@*tHTXHI_lX!L+khhqaeoOI(e5&I08)=7GG!O1TAl36c8tAlj;{~UHE%vd7CIPG z(${&6!oxg^^0_C41<)%^NtQNLWRlt(a6%2s+?j1md&3HykeP* zL$pk5)dG`kW=HGFTw;YP^}i@ouh)Z7R*jl(zkfZjv4xpZ=0WdqX^lJ+(W@G z^Z=|HP|UftudVPPH8P;uGqUeQ9G+vN{1 z9tO{yfqFZd;Y_Ccl?EyZ%r+@wBQt&SFLT`4!{F`{2al;Sk+pr*@9Ye2V9@_#>@B2dqp?f3kJJ?41U zT6X2kThyZ}hYt?X??`LvfZf{6^0T)brmn+R^KfZ}Y|2>b08E zwHwcJQYx#I4^=WTKt(_i9}?rKE#D+iCcT+C>-?esSybO1QH-qYRr6P8z9+2EAqFQP z31dh~nai)fIxQR>&6!nU^+$GSHnG(D^v?bK$)jL^K=K(E!TRx#(m_qj2H{_^e<0Ug zh~!otU9N`{g{H_>=66h3Vaaj4f%1(!k=jiB)H>CDo7L>+tUV7LsVyKALo?*4_g8r- z!&*-|<5LCYXD6^EOi|h3_Z6q-j(xTq<|0@JEw>TtoZte2l(-F=<$Y!}Igi@YnKaaf zF+5AZQNcV%G!x9hjs>cx{bPF&DK^q?cstQ|EYaDrjGaqv4I?erhH2_AE0%q)sJEtKXzw$@*rEyn)&bmTeaZUUEkqDdh z^khC_;a|Yj4=uX7+)J>gC-EnTn#-*z2w>mi zw|T~eu4oY!Ule*}YG=ygrA_4@AIqN^m*K;?{=3!@zk?((rT^A?F znxgrlDRwJ-r_VFSmA#GYZ);8~G<~=b0e^z9G@+JMXKR|+gHK#-wszX=V|vQkg92=i zPFYuaK=9XJ0^-8v8>)nTaf0_4J*88+{{iFy7TN>zOV=7Fu82;5|t7)w!mn{&b@va9*lO&h$KkqQ^X6?<+8h$MjhAKE@C#$%@G{u{K->3d|#dFNE zpac!7{up~1WCy(Pg~B?T3(p5`fc2R#@D}#kx-whrcr4^`oS;h7S=B3Bv*B5NQM#qr zO+hc?$vSwW`sc=I-A}31|95HN|2bA4+Wu9Xri(RGtQF3iL!cq$%aSur$5QWeN?KJi zGVyoZhUgYAgW4LEt?Jbb2+!@tgOEd`e(AsO;;Fk4yqOg7#D~K)!nj7PaK^kD0iMmN zLQEg+M1|h(Q8Ascu3|TV+V1=|mvQb17*M52QYkuf^UIBuYQA-n?UY&e*Dc90v_4+M z5P@;j`_co-ZDs-*>%H(SJ=DyjDJJI)q0~(G4&28;|qjgNN82J)!HpC2d@k}M? zXXe*3Nsf_pHnC-}5-^d3IcraCF?@)D%OHRSL|KW<^=Op;iPO3EnhOM;ZP3hJ>ESUg zf1>2p+&R=90z#=<%}oz8KT!Pvy99hd>t~j;0$4asIGgo9(W0g6l^|UuYjRAU(qcF` zOp$witC}gUU}Uw=N>nhY_F09RE9M+{5Vd?p0ccLx7HulxW!F({-Yk5We5ifNq^p8; zs<0gyt^+);XAb6Xnq#36IyBlr>21=#QH)m!S18NBI=m;%tcNu1hncH8X*QVgmdCFx zT9q%WEIlne!BekqED>0~+zTf=Q~v?~%KcQ;%aC&FmbT!NnW!AH{4D6*M)tl_6C5q? zdYt5t!;0#E%5%I;ewI)lvnBlCR=suK}*nzyWFLsI$oG@uGO z>JhhdBil5R$2DBECnjl1ogUxXq&Z0Et)8R?KK}=l`TUDAG#t0VR*Kt$D`yS(632xJ zkB*RF5cn;SEeOK6c$EEMUD5hZ1jX8kdmVp+`x*?liUBGoLlyw3BaS=d#?I!@9bW$J zY!V(Dk|EoJ|nlKg|7lhDu2yv`VIB5NZrN#ituGugtfO@=;~ZPoX6Sr;)y4d^3~c`y&E+t^cT08WL4X+p z(m(|0d~zxdtI|H#lK~zJhp}1`M#8a7FnVO*7^1`Cif5}NU z13fo^;5QhDw2g993LV5!9x_}4*(J>FYg)6RJ`sgJ_6}rqrCb=CfY(FW5R@cL8_=Nh&_)-l zUCkApS=^S+-H}VE&|PIZdm&xLnM{>Fj;^@fYb?H!sIp7r}?R&32`5C^}W8L5kDmttR}{{lue1fwmZSqfVPwf z(B`^PYub>EX|*(0p#NYsm=V^krF%w7f#Xp(5KjBP7!crMS}?l-Lz2_|8Z3>PKt8Cg-pFL53>y_6 zuPN)u%;^m*OVGkIHd8a>%pB`5BUQ|r=k?|dC#)e z4pDDHdt=QQpsPGaKw0jV!V<84B2n%BylCezKGeybt230;&m`sHbGAdF?R1=%1=rcLEY1`Wll#eeb$hARJdh#h>yjb<{P?3u=Qt-)s6Bc`$H%h& zGB>UMebF!lgviWH)isJL@g2i9v@34sLJ$3%T3d<9;3&k1Jdmn`Y9;G&8l1oOS-h0^ z(Vs_aPY7g=7%`bXkkd*AiL}Y0tFgD~UQbwd@0A6zMG}SB8i|YR3HAzyP(*lK9W3}% zo#L^lUUK#i4Cv&WXp@41tA{`;&ydxglJRD5%|@&|>sv|mS}(uB9ymW{CzG(3whzG{ zHIP1;#KN?y^abvQ<;LsU!@`kNK;_GS@m|7}=m5P7o8tjF1*8zc> za9?Hky+TQI3*!}RT&rtPTCzoidOPlBKGLEzN{-+lyx5CbPvKS^Wtlvtq``c8p?GLV zaidYG?FV6fq}dZD%SqwVx71Rg)R*i}e3#TXpF?|SNY7MJ!#L19INF@~V2MHwU}{XLKqcGZ?`;-{Y;%|bdf0I+mxqpV-fzn(C@%|XZ@u#( z4PZRcax-9vJJ_}vA6imGcA}NV2VXj+C->wm)>{VdOkxt-DT>L89ydB-1hg_Qjsv@mY4a6A!_7n4I zXOQg^*j0If*I%HAcvFeL^aLxAez}~^g4AX04vrP?cTUELPw&GXG2b4XVE==XIspG) zMcL;qHFsx>wq4KCx5xLxh@J`FvxY8&+E1P%2EJRGRuS)VH~SX~0nAkvWRKV*%ytZ+ zS6v)ubx-#$hGFsC!z1Sx=)OJih4SAY0-DU1l-m1^k2rBs9wECMzkCQ>ysC^_54e_U zsDJDfFCJ?(O@}tisfoZmz%OATUzfAwMd<~1WxmOKbpOeIR~|l%`*V0Byz3ZFdpED6 z<0n;|Eq4*4u-gaLLr)eCM`mQ^AA_OTzkf2XtHh|IN{=b=m@zJ+42Bqd!8zWJId?iP zYGU%p9}dSmtuEp5LfVzG{*&IqTj8x&owSYmTlBI%tzgZQIPnqX<5z^0FC4=Ot5I2a!mBIDh_omL9RXfcIy4CKRv$2HpNq7QESfg4RtbkZ8c`8>FRS z{xq$N3gWK$2X~x7+?K@Rv{6P?`s@I;=&)~PF=7tmH8ihpaUD?hnPtLxGxUvZpw(r2 zr_#-NJYm1?gqWfK5vq0YIMBYeGn@Qw)lf^j!vQ3Qal*aNLXcZ^{hQj=$;nkiOON-jtzzAxT%&`Kt5TALUWTMMIuxjFX1 zMi$Kc%1xtDX_5(ww2VLifaEi`8p;{|uXwTW7Ye-df#$`R_Ua3F5)o4o@O4bQ)qlX` z8^XV~T9=K_IX!~Z7MM3b3E8PTKT;HeR!r6|+4 zsIRD(LG*RGo%LT3G`G#Ow#m!-Rm$46f>I%@fyo{IZVjL(2WKuv3Y3`IO{enV#98Go zhiW+2r42Eh#cS|2rMqk5KxWc$wrKYqvDnZNsHY{QkP;z6&!e)*K zRUw^|PFs;fx*O=P%*oJUn5eZ?zRhb!#r-i?{BT68!Y6^wZQHuoE7D)f{v*vfKJc6g z*UZZK+ZFoO%JsH`FoGpfR9k+2PRsM6E;}Q?GwA8bXyPzBf;ornAk~w-bV+Hk#YF$6 z!*NEaFEj6J9Lj2K2Hac6#`a^YLmV)E&z$wDHFg}#)@w6pQ?5gQ?OW*Ff5PCjmhTR- z_&s)Kn86-ix`F6kYa7#c8^n$38`)_Z;{g+~f0s7QqfIzJvYJ>E@WgZ)IywIE9_+XO z1vXCXFS|m?54yBwsXKe zw)8JkMdXRn%Y?CXAU_^WOz%``JP_^BMyoUIiUX`tshPN4THkz>;og2^D)tdKdKVLF z%ivY0CnT;P;o0{4QvAJ*lUp1d1H0ps|BLH)1N9%Kf9jrS?fT2@Bh$8|%Wl7-JEI7? z`MUdExAB*13H4w2;>}}Au!wbk!Vy-WJRUh9t>SmARE)mXQ*v%^!bwo<+)%o{kABxI zIC7L93Co(Z&uGapzuRAl*7n+Aujb?K)2wCE-oL*=a5d>K1JW7y47EQ}1S1(J@wx7;k&0w6pn- zfA~qZCwv|%@dX2V4<|mF0YcWk9)cfGZ_gaJ@mr_8W;D%m54cA5G9jccN;wO*ac~&0 zot-bPgo7eyVsv?aZj}`=%^X+1lGdp;QHJ;8lhny7%#uisdmk1gfB$@^y;4(h@cjmU zyLtq+z;nt{&`l$kT<;c7xU!>)(eFI?=x9!w@j98rUN%X&x!&VG6Q@7_xSe32G{PnWg$w803Xmehj`U=@Cckn*&2@L=`8Df7 z-a{&fw1wl(ZJT0~pKxW)Iv49}>*`buNw24*aqAtk{Y%n2>SZ;1RyK7V>5g?VBDP|7 zRG%50H?Pc;nynJOENYE1zoBY}gU?z95S= z!uVGUx7aJd?C2z7cVcbWDQetV-;)3?pO0#~Kxv7hUo|;qS=ZLVdHU|}*$o3P+C;6A zt7+^I3rIfxPGa*ivtJ+a?FIfYn4`D@jV@`CJD;KJdKV`hcQaoS?L#S-Xa3hUI-E!B zgZ9U|@cpX1Jc98J@sd-u^lU*h7A@QmLWN^IMW#Vgk~LKl7!9DUcmf4eUO5O^_@U(; z1uoQd(Xb4?O^wHheoSJj{<3})v7|Nc_{7y#D(B0rP`-6o=w`+v8=rP8pV|l8!H?tn zoU~bB;IhoNR@AvzPnp1eh)^b*E^%AFae1g>h3-+_sz-ywf}RbZ;Cn5k3+ z*-}e@=pOwFdfoj^abWb~xVNBG#b;_J-rba>rM{@!1San zhEpRWE3IDR+$G9+O)Y)thJD*PuIHU|D~ivlNIkYytKx`%Xl#mG$YD+FDR*&hw&IYM zfLijd#8;iFX${f5AoP^@$@JZ z;ATyNiF4pf_9_)ZMrygNVb;l&6$6V+;G{ob<&{YyiG5xNsqFF^tLK?^OnRj3i4t!P z#ri6ehL9C?h0M9TzxeoS8M0Z5yGf!YeE>EO{d%3Iurc4E^xxC@_3~AEy%cFSftU3y zqur{UC)JVBj&D3wU%mFJdJ+HLz6Os$MB0-!fhseY&zWGyUl@8|CPV$msb4ZrmFy&~ zv|xLKkbD@Hl0;WrQ%jbTlh%P5xFpr4vp8X*kXIu#TM9O-E=aZ5{QH8l_Dz^YDu3qH zPn^_T)&Dczf`JFxhlAH>SNXQeZsy?T#HMVey&P*RqRNN7-mHWAp3Gbk*N9ZcK{Mme zsh`V1{CGaD{~h4hd;~yZodiC&{b_$d#&|9m86)4W({t2A*tTxcU_w0{V#tS6pAfDh zm>w9DTlgTE2Dk}!K5hNRs^yjtyrXyAH>C2eVa|n!Z@ZLL)t-4jLIjNNa1Jn`CQi*c zD!-IHAdIfg2CO)OfY85XH!v$x=POW4s#o|#hdAtl6{e03H~aZ~84f9F5R3lnd6e|L zGsYwA`}`dr{*2gz$H~EyhK`HCWy=%!l5(#Fy;&DB-DQ9|Q+55j@mdJSm*i^u3hv^2 zlZy&Lw=LbG8leelO%Tqpq;q%keuw9BMXb-ws9*ZAG7$-{gjSYvRN88Qla41II=(uN z&i`g3#9jsdCA~t{mw6GQV2@aC+J8d&rjG62Dsg@Y3x2@uF#3VdtJD^}kuuwn zlfyosXMseusP^kSA@2R>TlH^oOT-22jLFm}bqCyi-8H?sC1u3dy%*F8NE#<9#=Plu z14SCb3M*wt52O=IFgGJ*G&hs8+-29nvW4)!62;TrH8{b$MD^ZfG8=z&pd4sN!^M+a z!CLLyw^qQ3=wjwkf3n!OO|#?KL;RgQX_=Y)JY?&ewBQ(HDMaF2scZXrAbp#l4@iYG zP9~DeQ==!%)7tuOJOLX8`7-^0JsoJG4Um`gwJ)ZI2q}x1-k!APBps^0yx<9?d2vBG zR@zczM?HT@>;hjFfq_{o16aAvd%Jl~Zh5%bfmv$C$Z(ZP>%<+wlRRx!B7Q zJxPqdYepLPEH1MQ3YWrPj8?uf*%XhR ze+T9@LdEsFKQ|_(=8FmNi^CemFB^cpFwpke07IG)*T=5wJpQV^cw@@(L>`ZIq@@9< zQAudRO&BOf7uX0UfjTh;E&(2qbe{@Y4+rLyliSZYOlA{{= zB3#CuWj7WoV{EhC%f7_kc#7zcJQ5m}U}FMWiLS-G9OxPY@%u-fAlGhK@ixYNw)(km7LwAZ~NLYLeg-(eIDjuOiA$nGP&KX8xYd3d^2C+J=1 z@_6-$;*P|wR&?;SUIvLrvpXu6Q#2K`a9jE*T4eueZHR&RJdcU|rX)>FN4x3oH)5l@ zG(1}3FgH|ukI~Ur>WIO%Es$4(t5vM(?HxZ5)=a4r0$@qCsK7~_{-U#+H=38lx8A?y-anw@&u*nKwRIsKw8>|9;c@4>Qdf+% z%;e9wFlR`7O6#+DCWx)eT1M+5xnUM~AgdsZo6#PfNC;5DszeU1$1Z|b+i*?W$dZS-HoGD_1#bWl!D5~5>`g> zT4$S=Ked}@dn5J6@+RG!N5zIau-hth94dZjMZLjtm7jlO(DD zxXGhFAqEpBqisLyq3{%o7t>J_$=;F|(i|Ml~r=(MX3#}p7E%l}Qby=HgHwAd; zZHW0;%(n0d+BqJ6_6O=FJd6-mGr4^{fwRauiTZ}+c&33qkNIrl#zu0h5A}bZLo?}4HOJr|}R zp206sksNSglIGX;JlltN^?KD4fEgC3_!hrYzw$b^Z^{lST;Hnhy3;N~(#A97*N(ZP z_t|%Zlc~wiM^A8k-41{L3xz@QuVS;O;@N*A{%qG{bR*9(%D~$1J&FFD=akUzNphuH zc{&-3S?#qpfh9d(R@S&3p1-qt+lp572YrPZLp5vU4z-5>gP%1PYI=|9c=G7wr-ElFGx*!xS18@yGcrsl6Nu%mPy1jm8(ae3 zUJKK=9VR48P9=nICYMbEi?}` zG)gLf8qCy+?duMUNLJhxZe3~&fT~OOxeQ9aAz#+dS~gP1h`4L9Bro4XB}ytjJ};ja z%oyR=j7I5s8|VEDAKQ1*rF1M4NYQ$DAl=}-=WTW~8We^zmY-_veAT|BwsoaDxgJ0J z%ZWor)3NlD^%(mY>^=v0*nGGnrTrZSKTqkVU*4=(t{+fieOpt}!27MGj^@yDNH=Cw zkD~I$K-*qhOe}mCXz!QOm?E10WbnJvvbyD_2v`63^xMtY<+qf1PjZHB$WgBAO|`Mp zA?^NIOVNuSSgYwit!L)gWb=#GY5MTG7iaPbo^=uSPnRW8>G6Ka;!qMa0cPH~yH&X_ z5we(L>6!u2m8<^67fP;faiP%em(NSoGaCB$kI-+-<-MC$mod)qteo^e^e)nqqr960_u^UER92e+#6y&P9 z`s*OlGhSfbP+Oa&eU9myN%vV@pvTUR3Ldn-sVjoTH1K6f*C?zC%GP-tGNurx{Z=k; zlBDkc)t3)tB3LCn5Y5fa^hQ)ew9DgWHq&}_a;+nVj(`H z#dg0^r(9WvMhV|A8s&9arQXQ_DP9Q?}PJDKMd=&CGvW#=K zc2&!q(NcL%YZ+vwddFd0a)oC;!~oW#}MD+;ykgk(H}XX`B3xfubbeQd40cE z#|!dDVYRni^meVN7W31wde1({dfcbClhADj+dO#D5?KLKYFLJjWl>+SXS<;()0#WQ z@s*DH5W4IW92)bxgx$BeIUoD?`o>s*h8fRn?if@8APCYc3~iND3a8}1qtjHR;S*N{ zUr8E$iM7tQ2KoA!-U^*N-n`?&hqgwa`AgmCuq5DI`iMfDOsC}{y$Qd|NGv!YaIShHoFYJYLIL6s!(i7@1+t~XDYOEEU9WG zLc5!}bLt7^5s1Y)cHY@XYRXzJ+*h~Q5SFn~gn>KP1Rd)5esg(}|I!WzQVj0;LH|1x z$g~0rADCNt6Xb=MbZq8D z?5XI`ia%K0ysv0 zNUk#OMKh<3w8Obz16Gwm5)N!rlaPFvn=C9CS=q6-Qev+& z@G!i1CF4LxZVZt!H@c`-xi2=&)Bu)5j0FB#mdkT^D(uvtjH1-Pd`L8r@!#NmqF_RvoRIe_vPj`RWpj z_`M@0Sip(}Ut)v`^EBp}YeBv=?+=~p+>Pk)&GhMNV`QrXQofF+A>cagy7)KDPw4e< z@uHH49B<{;>Zc8SU9%K@*HXuRvF#Z;nWe`!mYV&=r^ZVSns{de{KQOFuHW^uU_))W zc~>*-gZXUk=xPY*fLrpX9+mN9mR~T-21bKV>fpwa^roC+YybToBML3Cs!|yisf232 zvl+p@HA8$FpDM+gCMX*SOvnkfe5;wEDfyX_uPo`;3y9CNu6two{+f8?p;q5;t8|g* zMU?WXb4e;ge;`#*uSIeTNFZNr_MCfVn0=CdA9fWF8d8%D*p}{Q66CVDRNz5clq@9%a8Z@GZ_qRZ{vKI7$tP=Wx^D-YDD>Uqt zGJ7@Uu+wh@_T&^Tqkb~GO6b%6l^Y3-TLIa<9`9XB;a8vgbq#hILCblTgb`5fqVa=G zZC1+8Qd<3ahmRP>^(C!4+ra5mx5%eYIsW#0PfOgL<+dkNj@ME~-ashn1$9-&!7Dfv zc5ef9Ekm~P;)#s1Fyz9dWiKRR-8mZy<*pEXYA=KQt$`l`IWCq9okBYAXwake0@NL& z+`q@-Q|~f2@@{qi-ap`e?FFHIgV4|%#RnaMaLrfId}gQ>&2*=={CVTvAQddZL?;{F z#Z3H2+-(mZZJ>nZoy2$rIlsJwFCYZjexoV4O&Eb0gi3$y&5|#rOk{4^^AMKXOVd7d zB`#(5{bU(SrdMrhg#X{g|KC^UXF$Xow%Fjr-iiP9)}7z)Yu@#NPL^1Z>W7-u`)MQ_ zIHvWor9}w1RiYF1WZ^C61clS_56Z15szf=fGn?osGoDYo`>PwfAqEVJ-mnkEBZck< zo)X^cNOz9bv*>)NHyW_muQ$x3YILc)mEF27Hk`JQX!$?(Jl5Is@f&1e z16H*QMY>#kSA|3>bk_V9c9UC?`Y!hy^t9 zalq~+HeO;P`8JW64@gopmZZHVB;ic!>tA;uu4nw<+q1%P5RL6Wr7Z2V!i%(3K^Vrk zc$Xeh?Bv^h_w1p+k#o=Rx{@DDQtjyTLXMufq8#Tce=$ScsHUH@W3U@b&9^Y>E}jyx zh}Y+wp*}24#z%L>V#s5mB<67k(oyp}SIy**uf-gJ0vT1ic~0+#**(UJvadF5$PYX- z!AvWYJ<@KS?tAN-3+ii4(o^+=9$02}w%HwbiDO6P);^q?!+;G2o3>}BxRZJGGSda$ zGg#@9wWC9KaG&40fJ8(2rVHYI@evy=iwRRNX|scM{WwK9{(C`iHSCRf!O;E*Z^{^N zO50ikxZ<^xXu-A>Ls4GPBgfAA;S&4Ki19X?9~x90p^^c<`WOwx*Txv1epJl)FE0Z6 zKWqM5@u>VJ{zB#Lc3r!0G;J5;_{D4Oxrx61av(#x%;)m@3d)@Q=bSZx)%K^9DhCBDb`^)Aa77@%8CquVgtdH@S>KBx?r9@> zdQ<5*(LtRot5L4xg5wIZo6j!KW9y23^ z!hD_RkvhngBGTnlz!;fU^FpCykfvaX>^#83fm&N%`+J=6Msd5DV_v)LEhN5MNu*m& zOAy&3aXQUA)T=lM`*VCjj958eYe%!!>1&G|>|ImLhA#hZ42cb)mN;6`)0Bmk_&1mt zMQ;xFspU|YCDB0#lbhqgV0U82+%GxJjt$s!qQg=9l$F!_@SJs#n&hzOyyVq~Qt1%D zK=$aIL21VU+G|}pU^;crP9$EDrJC0_hU}!jeVez+S_vA`01dlq7{oMFg!npc-g2Mr zz+f;jNDk{DO31RbTQsOzV7wi5{5)K?>;~U^tjSSW%J(UD$d^C*trA!{RIZfggtY77 zBNW?5P7E|dA^_DY2YT9AG=Pw}xI1LpKXx+WM5Tj{`9MDNs>8qf*S@R~>|U$U^9?M_ z|FXzu{JY41!bJEU|F>T;X1`KKGI^myq|N6opqKg>iiJ4W|NQ)I!yvwuT^?biU6m14 zZ%t-kbR}D=`?d8H9R@}D@13W5+jB}@kibY=8$$Ok2*kc&L3~YClqWHOstj95) z9yY1TctXV&Y9Jj%pru7Wsu;ZbHFwSdZG@wn}^RSwsDdTo^g>#Ev*lJ+9rMzbbNN<5=dZ)=17 zwxco1rw+>E(x=Iq5H56oP-D80V$LOJ9a&!M=CMlYH^U71%=XE}m!oqoa)+eyQfamD#u0 zehLp^Z_PN-KmP_?!Z9=D>3370#sV&5Nb_3g=9~H*Ic>Gm@im5yv+U2hTXF@4Wtc(<%WXgg(wCv*wLI zGMYlhEmJh zTjF@Kq{C06dS)bmad6AQE+2-?v3bXrEivg{q7~b@%j9?S@RE4HhPJoIt%R;!&SWVM1ZM*yS4+% z(*ZZI<+befPWpr;AlE__g~{GI%oRiE!>6Ny${4Pkk*iPw@v4Z0W3ZKe({9Sf`e7z(2@j@5gr(17iJn4Ye2o%sThwzWzgHt9oy;%NzIF+_k&*oIxq zbbeBeXTzbiC^3^y3GA!2`9xQo6xmI?iB^i?Xig~F8{Ey%cp)6#AmR34y+R*O_9WGE zqq%dyEevjG&BQG%EgEch+{xEQOu68A!eNxE2};RRmE}Mm1?rKHNIr2+_31v<56*Gu ziXy#FMUO`<{Efn)SN)p}%=#2%dpp~eXEF-iP9+k#{DB2Un%ZYG?mP9$_Rn0_4_+v% zr`?<>tIYPe#U#?seEdR$3ntPD`+E-Du8z7^qe2U2pP3g<%V(s+{dJ58RqIa;%J#n^x9Q+FAjR?e5Nr+}u>m!;Xj#A6WK~}h}dfKFsGG!`tNz?|g-VM4}A_DTO`IuBQ7b{EU5>lPRG=(Ui5_OtDA)nPu z;6BR+Zn}QnNY)XLAseBFsz)5{@aw$xw6+vUfO+WW!{V=5Ti$Uo`;^b=jM9*CqG@Fk zdWXA17!Bb2Zxk%XiuvE36B)kmT+ME$^%3&o08g?8#jrz5!YxG@_-m2u!NX1c*mlFQ zQuFt6xLe7Y3)ENa5_Dm#bZly|xX8nq18Ttm1Vd`R>vz&jdGEPEu4Z0qc;$l4E5jUW zA|E4ljh`qx8%Uzja>Sz<9G@;MUe4zd=MIo_^w&~K*Zk-m@P(cBE<;dm=Rh{ew^fNv%eRTT&S;UKZB-5E9!NRwZ-~%^3c0P z#qow7aO1V+*Ag_jTR}a21^1+x4xZeetn0JbNP+vSRiZ`#C^BT)DQ|f5N28Th4*%sc z%=yOz&u);itju%Ws0RL!1BSQFTIgDXw+;~X*R6j++m%Iz1Yy9v?_{w&QIFjOBc3bm z&8u{j7(_Z{J}0nC^S_PFk2nLVP&YZf80OwL{~^0oQd;u@OuUT!?4#qI>D$Z`nr&IU zW%_--gI7`Eb)QU$%sW$AW>|FZdw6~TD71rsjwA6p4*^Nb81llq!~IP2$V8fZH<0Ge zD4<7nj|&|@^+C0x34<`(u3c+Q#(ZvIC{Gr$s=ndh62ZXKu>r$t#h#Q|Zdy$Trm!qt zr0JXiH>#)FJe;{8I(5a9SD4oXXzW<7YbC)#u-xm?Uh6Sr1q(^z`Of?uU7w+G?iD7{ z=`V)n^)rmm!@_;VB)n^jJEN34+G#O7qSz2F$xS;9yTbqN0Ue%|K|9R#8IUA)`Z(~cJ# zs$JsXiN^oJNprm_f1nUSAPQ2xrfdKmROFWYbrGgx8C^+cATQ5yju|~zRyI1%rC4RU z2l>+^UKF7<et<-9oP73I^nHtMPUJj#=kUFjVAJ0v0t)0W%sePfsWP|nLENU6P8b|tMBl4;R^k%hhoc4U? z{aZS?+a13zJ#pss{c|$V9NM&vuJu%KpCu`-radOWuRRIZNA$tot#+AoI+-lsV`k$@9b%Oad zyN089d%2Ae`5CE{1%bAEbib=T-xXss5lgKoEYmV>0m*_UFS93;!hht{sQVW+6LUMu zaH=NG5jt^W^SGidy;Jk^HNOxujS{U_sEQ+wjYu(uCB(uDCad&RUSUpc8YHRi>4 zyBCZow{&X52i?-dX1W{_4Ou4N(n8xmSvkxKoDvQineAOHYUPcq_{YqnKe?0?=tb0)L)5^PCr?N-#O}3u?TEmQ>I%%zf$B%r{J$lTcS`KMR#RaKgh;aXoBcGubY` zRG6S@5Jc9QONM;$;P7#E+@etVMt3DnQraCzOOe{+#R^lKbrvRP8=LUbF@#i1{L>dp z*NoxCGknR@e$z-?k9Vy(^Aj?OJ5x~>+5|0?YXi}HfucjlWgUvFsTq^uX=KNnnkB8Zj@ylp#o>TCBEl7}(RxyL&3 zTRILQW^c;N&|Oqg>j1O?`)8uO*(H?B8*UaF^y)|IuC>Zn-5+50YT_Ro0G>JL*K3Y{ zDu|%)y}w9L7pNI%YQT6;6HeFVSNQ(r^EINZmg(3wa7d7>cWc!CS|T|PLe;QjJ{|!t zT{gNq)HFLzskgUvIsFqA(2tU`R{5##Z>V!uVzmX${{BApa__NCR#t5b3cXGx9)JsX z(cOSaSZKlo6EI9X{QM8}$VTu#dpaFMX^mV~eoJaq7%oO-X7qjez zUHmfVNQtHykIQ!nyOkHW0H?{;o-b}z`Ghe^m4aii^9sZ8gp?MHQXizyqi9FDp-yNJ zop!~XELD{TKE^AYczaYuR$j4?30g z`fDo6EZ3}hx7S+jgCxm11rVDa$5S@b;@E+fhnOElQ(C=HgPwd&Bgp#J8avXE?y9)woaBaqIvrwE2h!Pqt ziN$vxbs|#70IhETULN%Qb5~=0j7x-ebD;Sb`*hKhRN)O12$Z zJxoC9>hL0N4HjDu))N)zS34@aD2FMJCN<$+KUd@Q347dCWPSKZZOlICov?{6CDn=R?x(`^Me2ay898Dl2!IGgoG1uH0Lk;l_oy(aKf1 z%2dp4uG|w4XKHGRia9_*B_}B&nj$Kqci;Qj=YDek-haXS!Rxxt^E$_ING;C0+8arO z(pAK&O-P~6XXaw!$6vT+($_%`@1REZ=s%s0UlNxXJFH!{T-(Z{cke=rB=4JdcVx!TI>WS`6Rn7|6CjokG^N+(YM%Muu)OmUdcq-e+1#Cc?u_W0fY+*e;z6)tKamr< zE`n)-HkBd9cDh_MqJG;{)7h`p_2-_D-EQB|Y_1Ot*Gyj3?)X~lvdKRb`8z@Jy5yNx zezd6Oh^{`?>}T4a#9FW*Mj`Km0&P3n>GYnmqMg^(i41I|r@_FNS66@Va4X8MwHu$l zU(v=yI9%tsYZu(??i(&+QvAh9%$F`2Z&G1;%{6}-ysqOPb{4bI52}y~6Vfy0{Bd~x zX@L5nmo0aNfgdP?Hk$kOJ?(0Q>A3(5Tr6g{!QkzdQ5Mwm^s4W+EvvIn#4i5xA~iPe z%=&jX1w?MgJ1%=HDjwthL-g<$TU8k?=gKFiOq$KfIMbAvH|$*N-F+DW@6OD-tBQ7L ztG;M^LjLkVNpPqgcp;me?lizn?P7U9l1_N))y>O#^wHv%vP(stg_3n9alYz$S`=XK zana4GRGr#D%BvcwYS9}10(CJxg(blGs3=TH4o1nvYN~5}dLvpggllPVw*YO&7%}zn zFthBQyX&evV4tet;wUbHtR&8c@DrvBq*GE(nO4e>&3P{Pv~;Mwl|wy|;Z_Yb z_B|y3FCr=hul^VAJeo7kt$GhJ7PrTnKK$(DsymXS&5wm&I~Ud}-pSZvfi+d}5&z=s zccRosUexK#vPWs+=T*Jf)Ks?Kfb4)30)5ZEyhUSMwt#6Pz4^uZswdLVVwF8-MWQbd z(=b*1&ErMx795{@&YQG-hvL8z0V7|sUS%lUo(yb!V{6_Jr4D(4%H*AoshNy%5nfsU z5$R|UxlYvO{$8cCSNQA2Ne?B_8rlR=*7_pq8S*RaktBMD^{n}hA=dlwUT0fbX5EVY zH25V;Oq_bybJmLp*ZMnmLDl;7J1_0Q!ET=`?5qYN7x8Q%WLHSn)b<1IAg_g?(MOn1 zoJB;NTwvnQKUoDR@vEGiOyeB7joS}#wY1t-?=ws~c-rRiR~5h=vU`(*oC6zAs$O2Gl$KZ|4-NmbD8PIi?&-&)(q zoxOho4YviZ|Cp9}^|uMt;(jc+U3^QXMKgM5x;f5p?U3GxGMa4R8~W6D?*H=cbNzn@ zLSwsDYEprV8PrgB!0{%R{J|#z{xPpU+cS-(i13QNZ@GsCk!_lNcJ!wASl0}xX|T{7 z`DuyQ9lKabcyZiRFYA3vOU~Rt?Q8sR@*PiUq^V6p42eeZsWo2BZ=8O`)b?ECtQU3~ zrK#&ZRDON-_?GpU%Ut`|&&5!?dL9KH^Tdl6A8>%K3xI z4VqSzZmhPmhU9eo(<4?;ANtvH{3_U~w&1f}37QuaF5Q+U#GoZRPY)z2N1gq3M`_8i&m$v)9YgAq*WTsDx24B+G zev>iFOMSQBo_s!Dy6`$1k?~NKmJzyhL3+OU)rm8Mw5lryV*tXNtP^vLu3Efz%BRT> z3L`Pv_b$cs+=m_qUyuk;6i&dGR^`?$TOrIn@j^aO~5U(8)G8u21a_4oe zSZ?wCU2!gXE-&~eg&2IDcY)ASi?V|B6=Y~&lAXM(S%!0a@}hi3*PAOpCO7KVOPc() zKmX*a7}tOGGFkfyag>r!iTUKcknq-Aq5RKq5>sUKW?v+6`}{|Nrwd;wlSd<(7IT(= z^p?HUx5wUYuWxOVyAd1-%i;l7r;hx(O#PeznjhU~0=X9m(~pXNf5E$_iE_C#l72y+ zl@OS0fv~d)Gwm2UH*poXgU*iHqf1an+8fmrshwrzrKjV;JW#t;r*#&r&4f0q@n9d{ zhBoa0{F8O9wb@*rmr!@6!R2ai??=a7Rv%Ucult=<_OCc66xIjCSCUesf{KT?N7wOk z2I4G>+=W75W=VjV)MB$&NKL~RKliOB5zEjj-kt{qJj~3ma3_1y-*`}ZCweA-jXrDL zB~e^!Fdg;hYAsCWV^2V=2Yyn(vG0_Pi$fuSJ1mly@Thq6v3BybXRslfFk5*9)ye?0Hf}^BRg(hwaT5+(WkKbH6G_2Pa{! zwjNG0zahqP%7==hx!SM$+GTUGZ@NPfq)(fk7X#+J>yce6&M9$ERU;59-i}Kf+iF0k z+_kUGBR60Tj#cX~3TferA8!haOl=rq)Exk!deTq%Ds8P8K4Jft+4@`myGoB!yUF`o zuHseHjVHyyZ`3o)>rSMRv(+vng%Wak8Nuz7uO*gGdHY5%- zTsrI>Z^|r0y`^7U##br}6jWEaTLr2fG*<5wC4%i!7IT|)UZ;@y8lSw5A1BaSe|i0U zQZzCq2Er@yxJU~hjAz;D|N8b);FP|(_&ZKPf6sG|qoid)D;wN;zx|lD+quO?d-f8J z3K_}!Jv9wtdsqSc<~^Ufc$xjxC$stZD__C3nm1EN4iO!GxPNPLBTM5w2Q%NhRr2-@ zKX3asEUx+b9h4i6nLZb;Y5C~;QQ?8+x0Ug5RHx=ITKE<4cGOQh=$HNk-?@z~Il44o z=y))H0R#Ek2*1bZE)-bth28U>1!)xt81f!&vxu;|cLcpid>4A#34Eb{Fhs)ran6fB zez~7I^O^5^n>nM7?a+(=(lFL5lA(f zOZ`Ln_k`_~?Kj>|1w7=_V(-uL<}&Tc%2f2oP}{{i8C{apedV~R`*fasL)nmKzB}!| zWD!qQ&ZEb_0t6jgCx$p*l>h%REx_=q=`zy+4xZEyH(n zF83b#hU!pGYB|6DQaZ9CC4E&NKdpL+SZ{I3E2}wA=@8UW4Aiubz*z4WKKM}Zv2v_mJEQo7&12;!sG@ydK&uXyCIj`;zR_on5dJ9 zU#GfD9$aqOfEmXx^_bX+9k;q zSM-tPxZXesmiazK5!(3o^fKG4>eQ;@=;iQ9RC#aI1QDI@Gn&PQJr;PpVk&d%+?AZO6W(`yS37S33Z4|1;Os?d)z&; z<6{UTk(!W$C8^ADgrEyWWbG(KP(dmfqP}MyZp z4NhV#>zg>zRTQzduC1HyP7nr-pTU+g{Le8eJeshweG<5V9Cg|3j%XdMc&q<=MSmgS zKF887(oB$38b- zW9)Anw5_-sHRBrKU0DSkzy97rG%{Y_yb>A{dC@cr{LQh>N=znOX`L7F+QGaeV%OIv z;`OIx%;Bq^z)DnRt8Hf#(WllA3wt;68K%6a;Pd^Xk;@5#w{-P&+=PW8qDj$ zno3!(&E=%R#T1=091&8wdoAaDIRZpna2G2cz3NP?aebm66!L!J-N79qA~W6F0QM{| zr|O=;>!=}mfL5?UZYvJby))!#r1KDAuIgc~quT?tk?3C`b$N&EUiXWB77`w}oJ+*tF?HTo zDtKDE^G6I9VU7(U$^yWVu}o4$QkK>TS7a}BftR>)+_s$YuK+!l5^RW zGSUe8*$cMzrnD34&>_4=f`wgW+u-ST-&9+5$n`ZT_ zSWRbp?49NGY{_Pt?K-6b{oG7+;;Nmgscx?tEKNs;vumW7X9eL5i2GvyF4_jxWIdAB zZ({lYfdeks-r9Yo}qw zkwcgzo~HrN^0&TmUn=ASc%!~s$kx7?DeG+EkbH{ryr_ z9X|U3xr3=QRQ{1Xe@-6zx?<92MgKLq&H;LyoDa#V_vK!?TuvXQlM%&e_qHkrZY&@C z8Pi}?gUi2z7;2qTqZKl$nZGtvISP0I-vUrd@INUyl*+?dMO_kv^K_|Tg%tT{akI}$ zT~oZN_1y>-Cqc68r}yp8m+t3Q*&<*4TI*i;dJqT&=vQ3GZ{z2Q=8L0K=nXbPYLD;D z`=64$3y>x?&50m|>+Y|B=iE2&5xtw;rSB7l`R7`L$%qz?m3bypPLo`99k&jlwBc`{ z4}HnQgg7GXRoZTp_`Fs#6FC_*dbAao;@oA=QrS=VXSE)VWL3epvzY$y;c2QJFj*}?9danhezOS>mHZep#s=HTTQcrr6&Odoy>WN_(E zW>}QoF{H>G3b}Fi1p}r@S0w$XBldhF3zElgJY3z5oXQTe_n*_x>fcH)t8>Lw=eTG* zSE&uGLkflzN1=jjE}WDM<30DG&9AghL+0e^u%J9F>Q`CM`aEY-`>SFHqt)={M{grg zXKu%)H{~91)%JR_>i;O_NjJSN+_2tNYRZN;rp_GtqjfXaw0Wu#-Ou@V z9X%GY-^Xg)dV6;{ovCVgiE=HkC&X8;gEi7uUxupfJ1ssO<^VfjwafC<#3GsMlCY*S z{sIV81nh}~{iHYdHL!ho%F+A5WzWV-FY!~GogJZ6q)#+RGqrbncw8)$*(%>F)g@uc_KqVczR)OhDc5hHvxDfM~q{cCk-P!e6X{sK$fu1$0Ow z8~y_lAOE^R41%eI4NP^E<)-pxRt1EqL`@8)5(1VMVA!y+*OY@6*i2W zYV~rO;o&03S5ACFADxO$k-@;wtj8!Z=q~Sm5zV$n>)NMJe_YslqI8_ELS8->xHC!3 zK!$_y5uM);Oo>@Fv&HinWEhQn;+2iC)_Ki$7w(Hq-smiOXnx0`YN7zp0p#pf=7kcZ z$5}@=vUa^q$CP~}kO^!LYtt*Y3|Ag&-o!hRp?Y}pb#EJ*vvX8`JKe5VsiyB*R1XFVmQYsl?u;hL-(c77l zG^}=@oEV~)aI&2vof)~SF)TKx_IHyv7Hn5H@Ks{)aA-k6jOkotVwk3TfxzPxSEst3}&D}Vpxm)j89u910a5cI?gsdHZ~EmnuU#ZTMMxt zt&sH8Wu*%ic78C3pwVd{p_`kH)Kw#{Vx_NhfuSHYp6w3LEFiqQlK&tuYaDcb9$r}g zZ*NomXKUatt;zu1Vj(8-LY9;hf4pc%n5)%AU4#%YN=CepnK2V?{5riRUnkgq-GhC~ z*GlA7?Ze@N{oARP;*|VhPG|3TOwF|lI(nNnaBrE7Z?>-|WK+1hm-N(#$DdUpvpp0nEOpSQuDLkyH#Ke>SXthghs zcBZsNN(L7$Rl)blQ_4+#scKiMKo2}KIl_82^$YH=?Fb$)AD*20A4E@t2A?VD28(uj z5IaqwVQ5tJvS!r9k9Qe-bURs8lJ~m)`z|#DTH@~r)dU$U&BtG!n5~a(tihH^qW4SK zpL1tUw}0!p2GgG{@SNHam2(bz*Ul=g{Gv^m})zPfSX4E23PGY z9%}*S#(BLqcaQ1914@7N2SxToQU(u#=-_GzgNU!+4u5ZCHLe$o@A1}v@&JcwvvOTr zgwP+JtY@loBJARd7kBrw=;Rz1NkFZ(F#dNUKOsVD@Lva4-3$EHBVG7vOv67fiVTYo zGFQBrscL_J)r1CmO;ab#6KEHz7p+Hl_$%Gaswr4`YdURTzMmIwtFN%okRZYg2w4{oVN+IsCr+mNyQ-se#{}c@vC(RrV0- z>1b8?VQAYI=()h&VdgU2t(dCURHLDIs30Br(x!{U{iyrO4EuPCE6;jPPJv##9K-}* z0qlS~u9$IL)fm}#8}tPY0)7%W4R4uw{5EMDG(6q16cGDTui`>rrIB#C`Pna-9Y4_2 zV%ZNYt_r2n%3=uhbGbAIh25`!sn^uIze^ObJxAfGen?h{_eZGNkv5zrZg@{a|Co(y z_F@`l?DB8A?l11n`tK}lwuErbsv>-Tofh`3O6 z76rnEJ3Vikes3-FMAxF$k^c?Zn(*GH_u*J5!V*`!KCt`R$|AsXLI&Es_2*gBzOxE< z72tV4z5wP&a0F@=bU5}NJh)evZ$xXK-eyM!@P6-Jf&XY!2)K{d<5!QU?=OXt2f0rV z=!x%#&yvG@Vnp-Z*JBVJu=j0p;4GopgAZ7^V);K~&;At{C zOY6Ldd#)3;5BI(rL~&XbeOD#;znxh4I*;R_x&P$_c^y_pN7d!KiAfBv- z^9K6FBdPNeyB4*nt9&1OZuOe_@o{l?`3Rwp>?$)0(a&vt@pg|^TBnvxmd&bJiGsKWfj=mKVGu1)lJU zbEiL0#k8m)ihP=WH$c0f3Sw4c!7j>phiDD8I|*7L=7+p5x&DO$SbOf0@&}Mju|9MI z*UT7s+~WrFC0Xa~!gk&JRXqsi2})STBrd@F$z;6UL6LZf+&1=O<57n?ae&ch3guft zB4kNX>h`_6fnJ1GnI%{l!jFm_Zd~t3D$=m_Lvgk7$-D0#QqkTISf4JWiz56eT zwE_%2W5|JDROp|!iS~1h&u>2ia4Qmwxj}$YfIImRUSIpvw+bbS`Qn^<@2TknkKRo9 zbh%ALgc+1fW4;z1X{069>?}Z(9Ld9tM z`@>rS1TKnka>E4Yz^?|8-_Dfs;;c7Jz)@6gy4klrfiz{j$@KE~^|R#=xn^hvnG=*i zgBs&6npQq6R8fq#D7nA!S8h~qWYJYSgMhJcw!8hT$vwLniylb37ig>-lLpdU)6tob>Qz=Rz$X?$P(PdOik7wM-tUcy^_Q$-iWR z2rFO#QD3N32UzsQ6oHk)dgX1(C-0>d*C-uvDOr$If~MOzJO*R*TX%YXg-H=HS`Qi3 z#ETB6M=L-1*vk1W&itv38sD6fGyThTbTwPm+pPld4CIEIv-;=*zDP*F3nB=0@_M&Y2o74b$WA2C6XEN*;$cULsILdpzNIT;)li*MCV(YK%6@qCp8eacn-O1=(zzPx0+{e=hf(J6?#EE*OF6p zU=Vlc%20(yi9x03z|P*x$h=p%oKQ*aBuQbT@wbI*wSZr-Q^&MIrS{oz!!^clcwR5j z+bQ@RB>q0R>S=~ohs69%(sY*8mSa5m;b@Ipvf6Ae-34jsW9GJ5-$b)`2ZRNW4QKz; z?9mUQ(;N3<|L|B~FCwVD+gR$jev_u_+RvkgE; z_EWF0zM#fayQ5kBF{ktjLdPbvv%kG=IcBdLBW*@SsYP9S6})d*HviC2Ui;zKK8#py@Ls_lEk z(I2OQ_b0Ih=iYsooN>UVtsImbkfaXEQRxeJft%@b(jwur1c;^uZADDk^e^ zfNTVUQN66Wa0d0sO++_fL@=&%*{wzb@Xxa-+d&YS>0Z0H-l%@5mQk{GF#Yf6i;6!Z z&m5Gx2@EnKlZ)GeGAPgwRSIR)x+A-2LmA)v5h_rtRc(#fZY?lYr`gm)@4g^{`EuK6g zwyV|E?F5|m9P9K%^qE@mOmsZWl3KmnJN3@w;_zm|wFhB{I+D83;#u0_PzrOXZ743i z|21G(19aBnR|SQjcJC#gG3lTqz0Vr)SeIuaIz1r3?2>WFq2SH>$hVr7A5Ww7c(O|K zN=y`=NCt{29i=A>(7>W0I3!;@P_RnYBAc0s$|D=3hP9b$rtbzTbYCr{cJK105N3iG zLQ@B_T;LLC1h3%`XF3^WZ>w&I~IQZaJ5cOp|#q6?$-W_bDgEF*9 z=L{}ekyN}tVNkN`70k3Yy}H-LiB|KpUoW1)s|#H~+s+IR)jsj$h6cpitu`3IDuZH|xlnX{-nDkk z5rgD>_YR(3R*N{>RV}?0EBsEu!fEdfbXAem&T_F? z>lAW=U(Z1!-K)TNoxdfPVPB!3bn+4TL?zuz4}eVgd`ZU8lUI$mu$P>D&=^1H?EhRa zs(^hg*lgp4C%0YzLG*2DETlFTvP|(4S(TKbk;cwESt2j~$qdNM22!~8M>I>M3zo6r zde>JPV54Vcmb;Ta4>5!7YQ6ZW>e;CzkoOq+_7AT^pxgZo@1TK{-SO;SdP z=G}xETI*QNty>RrFzbl|l`lc>G&5(;sn0<;=u+%t&su6RvKoZ){#N)j%zwyM3w$g+ z8^yf78Z#WYH&b`B#%);;S(A5Fe>!HMrNV9bkCuy8TNV3% z{l%NnyY0*7y;i3qI1vr#L@$^KfR((3tpUalSrjv9s7h9Qg9;|{2`=*>b-4u%9!IE9 z;~;=Y2(%^@r52UG);{t8*-9O%1%<~7SO1#g1o5dC=0EhQiT;C6#T4JAU(qACA~T^>aY>}X zHCpST(LX_Y%Ob8%&k#?8Dnu&uyF6V>$Ak+>{DJ0J*rFK`u`xckRMz@y;M&{_HF_xQ z0>7=p2fs$%{$*I}dgHN$g6}LcX^!YuXHm7o2i_Km9nVN_^>4C=DYB(2n^7Dj7u&A@xt%=k{{1-RQldv znmjUP`(2^^T$=KpusfP@$*Ga8RpGve`ttM-p1E_i1-cin2hY3j4~i^%0mEkD4}BS; z4qr^y06k%j6462#DmC4nlYcF!&65o*EbJRwleeDKj{MU+5)ZK{Hub`0@sXerntc4T z(lw&V`R>^+neI7gWkbS29y#Z4qn{_1l)J_k!D9%Q_t~QLsafV=O=Y%49o5UQ)lWe} z!MK~6rc;)Kw0Pi%1hYYFk=Pd(}3qwM=rX|C5ZK5XnBZ2x_HunRhfkL11Gz-H=$S6Yzi zf*JS9o4-s?y}uVc9dczXZBc|0Hbi_tbQ}@7o{6|Yzw1}wxcWD8FTx_EmQkS+6GW!X z5*s+J5Ii>*o2IYYWrplXpztl=!@K4zgClT>!UfIbmOw#Exdjv3TfBTo(*J(=uLIfCH?!Tc>2F?It>uX$d36dQ%e^ zNOsOezsTY7Q2nMe@a4&zgsXoV1o8qq=S^oy440HWes0w*N=wj$#uo|gr3!Cc+2^Jn z><#+=q+GN|I1YBU4u$~xKNLA590fD)XWaGPu6JL|o$2vTVNe@WG70^29$M0qjtL1V zyL`h9+X#D^=i@61-mcKpjfe`>I5{4-Vk){@v@CwsdBpN5M?UA8azmv5rV}^GCJ(4) z@QmRL7NuYe!lIAfgPY8|6-%SO>mwy)w$<0ZWVT^=IhuW-13`jPAwPb$tB$Nb?93{5 zZ7b}PuTio>n_yu6ClKfd!LvyjF%2O~O_vbG@0#h;@FY05z0z8f zT-JFQ{Ek5G#6gmLo|C7|lV0(Rap#W!c5(r5&rX*N00rks4-D7Nt8ja>%U2_CMZtiU zxx#9wAk9@;De;jeOPhs;eA#r!esTB+V32>7y>j4Hcj)jWC#tH7Kk0Y|cCC{hky;l4 z^|4Qt#%!Y%?2mp_IB+7In(gaUWZ44!v?>pLCE6~WktTHAaY2*s&ZdpM6fS9I78gJC z5nxb41?lSl;qP11?f-RuCRs-(6F12HmOT8#t|_6@@@uf&0g)4A8JJbG_P3$Ur+dcF z7@grc&zrhte()us*3;&Nn-Ih*y=++ao^zft zKy`uM0rI@`@)y5JLDVW86e1w6Tq@pDl9V$p@M&$=N=%VK4ZC(vw#^=Q?)U564=tT5 zWt&xtp{Bd7<|%h}JUUbzZuHuIWB@}WqrakmeoFTKt#4phfvx5azOk}is{850Ctu0< zfWX>qU-j^7D^2;^g3sWBmK@ZS2)lk@N)Hvkstm$9<! zHA?S<$;iOm0Bxq`k!pW}I|Hs*VAy1LB&7pl;-nm%pw9lIIxTw>!_sl-_9(gE$+&{L9uhkIt{_YzBGZbtt2^kzY_0ypPNm6P^XzH#TOCwok_`&Ja_S>?W&TNkEgc>@RP zxSIju*j=m`A`g~sEc~*)UU1!PN@bu=6@sfwztZ)>-I{1&n3{R8x8EW(O;Ea+&6ivn z7`Ew%Ek|E9vrj}ap#1gP6pjdMd=T9Z`%Ug3jj;%3JCv9_0$OwZf8Z4TADra2agx;r ztUjl`bC3U&?rumnI3&_;fh$@T`c5@2!8|nrHm^?%o5`PnTBki| zt+@)U3d&D3>)Brsm;IW2eJZCnvO=xyAO(6m{4dY>=WQ=ZP`?sz2m;?aR2s%7&>$oNvZJ$p;F(ovmJh zdqwN~hvzIJf?=WaIare7-o24N^lKVT5Axx$-BIbnrFvM^NkqQ(NX$u|HDxL?X-of` zA*5(Ag{B)~a}lMA+}_=tahWcybtBw8SFi9|8}jXGZKXZKDRIcIM{HNI%q>y|j$DLR zd^PXt%S5bM?3AehOrs653dkCEZx_-|q!YX^v+}Twsa?qDt)bd!6(?Feqa{a=SY-8g zGU})G+i(>&mAcSrk-EHbfymGQEAjKSaN*kg9cZ!<)85~#aX?YXyn*3^F$X+%X5c*m~(leQ-*`8rK_hh_9Z-@qkt{d-1=W z^6h&tGWOh2HE6YL-Ge_#+DNb&N~zo3RA`ouWoDRGek<}l34y>%0$wSv2M@Ye?7;(m(6jVvxHL<=EILPr>5Gcaqr+1ge3}SgE6+=O(96Brv z3#Y))7q9gUoTIO|*Tqm=y)O1yLK`VonGJ%NhV|DOhBqjnspCBEXq$w^-UI3D!C$jY z)X~+HifEzK4*rWRiVtN-zc6*7D*Eq48h|Y+1Fne0Z0goq^)phO{l53=c8UfFP4>2R zS{j-;l;aVxS>DJCR)hjWY$FoT!}J1N9o&2w2nCG+oz%aMv-LtG#2nt*yp;I=924Px z$K(NUvjcir&9^4-)UJ67z*jT9Hf^KyU?wxSY+9_;@Y_Y1L~6tauvR9J)6q*N=6&Uf zH?%B!X4KElO2%DB_V?DD8@3I(R!u}x@G2g%iH%k!9n_mLJ4?Ql%(tzHggQY3I*&T+ z8^iS^>(~x98~rNu`T8LSMxyKH2Qsuyl}Is&+27y#Fx{)E#I<`77rXa^q>1|HHT8$5 z-s%YsXKM)z8!<*xilSmJ=bAmxxWnjEjGIUq&q^+GCb#&e4qHq;$>-=!Tl)n|ebL4& z;_ow@7)XdQy^(gge`UEYiX!f8GWEDF(+P=Q);Q13=GunO%xU<{B1L_3Tc<6#&JK zTy5?dDFp5Hk=h!qAd*RXqgdjn(iOh#G-S?5UE?{PJ1eYMKpGrod^fHft!ys9NdW<9|?>L{qF6rK5(NScYG16}e1ZCm+bZnkm5UVBrsiW>KX1hG+cWOfA!jAL7@QVHINaPCzl zV-wakndg4ZhQ~{698^Q-rT<~_#Bcq_n>=b(cwF{&XBgA?EOSX~;+Yrm4rd=sW9ja| z`E1<>9Ey%}z1j`DV?+MH*G&84kEUw_Rw2te z!?}G(NtQa-5LU%|4gGiS{}#6Y@dZjtwPaB?pk=wx?2W&vRCwK?~`XFq^}V6im%qBk5`NecI!$CPX*(?-*BhYtBL|Y zixY-76m43K?1aZ3p1Vu$(-qZb@`nA3im7YWu%nTL;-ao1%f$!8dav|@to9N%$Vn+m z8hl5WE$cm*Cdl1n@xa=W{1e6)pO!X>xMMdp(ka4apV1^;W!GZ6p(rE6f9 zAKo=nQQ#tgwyy1`gW`K{Im)=!f#+%$7oR;SnGM;QY8HxyZTs~7#)b}{svTh%=WPe( z*LvSC<=eN1P`tyddSZ}Gz~@;MeR37MO+CFbRaZhW$WZ(DL{2%orh3+=iM5p;TxvG(s@LI7JCAlV>&S z_!zI{>2PGEL=KjUseD1iZ4Z7rp9Q>>uJ~MxXi5Ld49j|VX_udUfsb5;zPHWP-kbr_ z)sunf1`h)2nw^4-TYs$cRFt0nZ=*vXtNqsnwPzw%81xoOnx}Dp(JhOdZHj;)Bw|IPgHxz$lG zL>l?>DFlRn--+%nV%G-pXsY<=qW2t;8(QMCYXr#b!-9TXtDml}EVB~DQ2X0r9p5Lo z(cm+r65lg)(RM*A9*6Q~K9oG@FW0B8+~=kP^l>ZU`JB6616tKSfnkdxpx_mJCqz4^ z&YH!H{Vpc>s8pqFE<|G$7hpPem}q-D7;iX@t7&&gRI^W!7PZH|>rT%_&n6iA zRAdf<)NSxK=P)OLQyC&rwdoy)rdEVqw-84u%C6eiD$mj89jHE^i}gnPIe4ic({gQ~ zpgFbsU`xUXEs#(NxPht4KMtG1MnW#d!M6`a2(pVOXVf7RH9wL0ei~oNdT71ueDICu zN_)%~Mczf8G40(QSqWsrXgV!}FmlpM@!K;gg61vf`j&&nT~7W7 z&CQ|z)!S#dd;-l*STo;1cnerl-{I+ZFq6V*V_-Tjfv? z0UzMRw?%D?s37Y$>*mF`{Xe`obT&+ydboV$qOpbXZhg*yS*Wf$RVNcZQ(3f_zwUZP zT1+!q2=IS zYppYP*nO_W_*_JTP0y}6`A))6c`>W(9*EUgqCt0_)S5~t`pD_^V^S>kQ9dGnHMHtn z)cX$me$No?Fu5kYN-kNmH9j-g1kF;aM7Dr<*bFT5MsaD&Wy>L2^}3`G#m%IkRq8e( zt>0M%bmE8eASUqf@J~dq?*~7mfbCkTJ7cR|{hDJPs_2^=WduzZpOQ;1c8TvLTQX1i z!wD|^g9r3~vXkN|Yr}?x?s|(~QY($UMlcu+ZazQy0M ztFX8-A9}t`n+p>PTdth>IbTr{^_gI++|p6U%q2kY!qvR~Ozm zsVuVJCF(s0aRC5&$1F*x*o67=m@q}VlWhinBI`pSe*Bn8XvEe2Y?-q@6bHpT+;Mtk z^wrGLMo@Bc;^d#;2jTp>ly|$6w4O1^G`Pw zNX^O3q0kOJwegB5rg1zi<6qSlX%8q@j@Jk)So5OkJ zlQel%Nv#{qll#BFZ5j36&qK5qhtz;W!`h>oqKHumFgW_xM*zKvhZ z?4lcderO;j|58(t6r*C2^5Sj~grLJLyE2&QtSS4}HPGX(Op$STmf|71IeD1K&{-yE5g1V(0xgI)5y<*aXUrrAoL?zfzRm%2`MDogJM1VVw{3A5od9@4u5 zD?y3BrrLu&9Ctwwf%L3}mIC;E<_WkLU}*8LpyoQIa1O$3F%y71|I>1K-?XePW4Yi2 zkPk_?YM5(D22alC6|?nkdJJWH9j6KUV*CkXh#}?*hgBRrFGQ-CoR5T}EgjZKF4JXu z*vcztZuO{Y`qZ5wka9MX0X`o)Q|a)=o8^WFG*H}GU|NHtwTWYHMtgV{9f-QnHG#BIO8(RlZ)g!IX5DFjEo>WleWg1 zG2h9JDMPJ8yS)E_@`Re*|7!ZkPOiKvB@9xNJNz4zLMS<}nVjvA`D$H@15Vn|cF z5U|z0@pz0s`jd=#YVw)cyZhd1N@VX$OvDyrQ6K=F;O*c_d1>#$dHkpdF)n6(UF@c> zh4yFOiPSxu>TTCtL&MCqk25PbOBR&^b=YGkhznM_&R%6@#(k{Ma!O#=h!^WeX~}N; z8#P-!J?xN$w-zQAp4mU4fu~&@=Z7ZWdrL@^)F*iTC}_d&&Mx-5sfw0>G~yeUb0x>l zjf{VVYoAdsDF|J-{g>yC@0O-fQuL?rhIVK@k{FOa&`_n}Gspq&>AR3yGNwF!sN}eE zm1mvtJN=+_Rd*75SoY+CK7VE7m}Mm>@Hw(#hOq*^?lokBPl^^^Uod zxk`6`ESe-VAtId|6VXO+)+yJ|pQhcaEU0BD+-q=di3u{jqksJ;XU*jlN?ZxlqdNDt zItpv>a~3QQsGK4?#{}Y*x11HvM$a{8*=Y;x*hOs{SH1hkbjzBcv2Wl`eP!W*QUf)US9|E16wg@n}b^fwOZY8-*Y2L zRrl5ye#uprKK%ko8R%eoG_K=+n!rwD+PB0V z$bKD2z`VkkHFs@Fmz%uA*g8B0pT>3U_PgN}YhZ|rsTj=PoYu}h`nV%#`7?d&<)zM( z^15F&oCKIL+_~zb+ihPi+}~2bHkNz&0zbUxz`?Rx30JCmD)y@llX|8;bUpgeDE$&I zx6fn2+DwC`+i}o8e?_^IODEPy^r#7Mc_0P(*@HA-ZmaCWW2wP{1k;!8D z$Lpl+LvHF8YYKQ(bL{<($HI2MX*C%_4Lxa_7`yDPRXqEs>2Xqh)`3zt%gm6L#9e9~ zK@d%oCezL-HQIczBI=XUTskJ>r6Ti>%87kH8#vRFOrA8c&-= z?q%Qu{%WMN(LV zi;U%zXc=d~fn=>)Wy$x-x?tD&AU&~i8rd)Uj(4(Q!_RKAOZh`~D==bdlqaJL#u& zqI14d!(4ioQXkIG!SdS89o7bnDtV&gc>fnoN!RP(yxx)dw%9Zhc-HK4)ZY! z^yy6LWACUx5%AjUI742DlL3Bpx?wW2Ne|1x>13{;x6jW{9;RA=^NL0hoz9q(&$@IT z%UT#}b+dG&vg7XhU)g!*f}=%T>6q+uh05dLeXh6O57Y|;N>{tt4Q05%D zmtPuS|Z(b8<(S&b!vEw%cFBScoICnhl&0`~} zLJ5sqf~s1@0fh^%f_B)AXiD{fKxHJ9$ISK*F5?Bh4?OdUvfF*}9S=<_H*!4&rhTSL_KCvS;byxps3;BYZHxr9JXWeeQjK`q`>YzSKkDc? zT7SEoU2EC^V}?k1j-+~X|7v{j*5smXyGOQe;aARx=^3_w5_;Tjfg2;!`TY+{_>(Rg zL~5&wrKi#$^lW)!IeOUM5`NDe_3%Z?3s( zI~Rk9FjdR_%(;~1r#P|8+7_nrdv1CxN6Yv60epFH+)Y=|nES)aWx5t&0@}C)(|;FJ zy0S8VGM57m3-UB#BuqP5PF+i;P7cqMIohF&3315fZ7q*2GZ%Q6m{P*Cj+z=iZ7d_x zCqCkCi7KtUThy-w5usSbGCfUd`|9L;eM1yN{$@(=_t=Vgubq`D1+~THkcQG93lTEL zA47Y8eiKyWT&(B2&W@ndV_I}8UpMkdm28=m)5*-K+L$`iD*B_o5b%iGPAP33w5+iB zc_rB2*ZLaNchXlFF&Rla0}pPaQG?YpyLasLA1>9tcq$wu=fjMaoR9JwlP2`q3877A z8Z_I&!;jm z0*{1mn#nWf2ZIv8x@wmbVqCSw?c}d(>!pC@7ugeZqkM^?uY_0CU* zv*!_01GN}Bn5nsJp@90#J8xRn?-|-EjUwc~YCiPwY+V#Gshf_wsJF^5n)bF+{tfZ} zHR1)~&P56L3C4{xI`g`pWGv6GRo0`D;7dA?suwcYWT1voriW0*y~28VqvxniiInFB z$s<3LF5w3DS*DKJya1(OR#{zZ<9}pHq9Jwb6U4? zp0}R&_`M0ytkicz`b_%}cL~o?R8u&vE{+~(qmMI&wb|zot-x-40k=}z-8W^&!vh6d z&|_Y*$_L@&U!QB;zbQ%y=!LN6SiJkw>5jJ7?mz2h8!!OQMMB%ju)?0~cU#_GTDanb zBKwB)6wKX;{a`ub*t6cVajJCTWBA!z9MA3KpT^{{RUWx>%ZwE$j8o%q$pUQ~;k_`~ z+#8HD!WSy|G{GZVPSKvGV5=05(xzGVvU_wL&C zdYKip)vc_dU2AiZqkT4A;l}|6)(!Sa)^wB@V}H=QR;_}C?^0{f$aiwGJ7;O+YC}l{;h^4ZgtwvH{fB#EP!3(@E3-2h*Zy z!*3gxV?B^v_P4BYj!KE-64sIP37sOC9D6XUnphz;7e&c;aTYjLsJY6MOvOJg&V6yNo*OJ|E$uA&u#nbG zE7!DvAI)@F{B)XH1-+|>kx!sYe|>mgUa#$bsZ{M^x&DPHQn^zt!GrVmZFqG;`U2w? zM~Us{hU!(C(lAnN$pTX6T{$qopAJy}=VvDFr_FBBJ13!;^G614`cYkSdjJ5}X?HMB zY!~PD4L5Dcqvb^1-JI-IawwHy{&I6PByYrf_4-+mZ?jni?fLP1qm)`*%*(jmi4gx+ zql?Rb4N6VU-s>N$8Tu{=-B=8U>)kLC3+S-t>CvWrdIjG6%3NVgb28aGpt85?D5;L} zNYmd2EECfX2M~!v)lb_zN<{&=U5)DS2IXOZ!i#?FZloVRmZqNe9%W*W2JxK-=xNjj z!!Deqft`VuMHp~Yc$x_4<&4vjW$VpG`$?(&Sz|G`{a#oR^$(@^A#E=?ox33UI~*~; z;Q0Fci=~^=7TG@Aek{!WB)X#mRmB5+L=xyPk96Z@h| zNBy}9f+@}o>=c5@iZ1q4$dexawq18nV}|2-3F;E2KCz28-5p{{-R%Fs)ZT3Kb&m^Qj-`9J+ zv;QeyOQXeIvGGh=hhSpFNu4qIpcei;=?SzCy>a#_Qr|7{w3D*j1^H&y@bq9_5;m6y zg-3jZCM0TrK&bIkNFU=&l=VyF>cXA9JMUCrWaTpT*W!9VQiu_p0y~+;|mmzz2#iYE)CqF0-g&Ld1hMY75?_M3DK02)4hT;W-B-L+jXMLJ%MEp z`f+!SEG~MqbYS~O8aAcT1IE@fPP2V;YiEW$s&%$@7*d@V8MYDa$B@y~mFWaubRahI zLP}pcQlns4E%1?&p{cKt&TlQ4k%9D-iGv=19TsbHQog$+iFc6ctd^6DviBw|X^4h! zYQYy%sAQh&Ox?G!{sGsV)B%MpnVg+QZPp(8-0U4bKK){FeJLjPT3dY(zhuwSp8bUEW3v|PAoiv50N$J`@A{alxeWFS zEEYi+(@gF^^2zN6sr9%8G=NvjuQa&~1ng!TmV-{0 zh%-BNMx~TeOwAfk2VI-q!3*e+NQ~Ff;Ga8kY6x8$fC@7}bIWV$m4t3x$T}Z&|?=y$lID)jdhGvfg&{?4cb{S0wd)>}U_dnOeJEbeC zTz1@Uu?QY^hz|R@f!IrTEOIyXdNuI10y+zdZ`oVLQ@XAaH20~oV%lJN1iD+Hsm5>l z=-|EZ#UFmh-8nYoLyraf?Csg&z4 zQYeOphPsg&1043#(O^rXX!-!BqIHzVGEkR@G;y1f1{fW(k7DQ2SPO4X>Z*OHPHwOm$s6X83 zmP4e<#A$OOxl!}P%l+lS5&#+Rqx zD*?vzYtZ!VujJhz4L5~-h4P90gp(%jID?8v7O0#%F2P|oh*RC|**|*YqQH}Urj5L0 zHZ{f_ZAok*%B13r-!w8uBF4z<=t?hg;)mJrQiryNpdipscVCuTH_yyjgZdL=tbPv* z07d3am;T0sn+*Mbg_{QEydGDA&UOfxf@6_c2le?OLQg4)Q=&XBQ(Xh!a!8evq+a?$ z_75L7iK;ikLtAf-O}5o^`R_3Ih(_~>^tpW(!qj!aw8b*I@tKC?)SVwZmf!mAN`y#* zr%ZS6xH`0Jy+#pgGUwYlRG2DQv(;7-yeGY<*{^PGP=hF;b7ivIS7qH9fm z1C77UWozz2=vYjQMy4ZY=sRlyCM%YkjFsw)pJBM!6P%=b{ME;~Yuww^02-@SctA9BboXWuYef6ZrOF-)|JH9rUIV*n~(F6^P9I10C# zQVODWj`0^l?e^30gNH6{cmB=3z|Oc+o)Qho1MOug80HhawG_$ z655|gD~AuqHx%vk6aQkBkLg`js+`5Dc(Gf?L+`WBUvaUKzn{^~bJwA(NzN)2jYgmK zvpkOtbjh5R8Q7>zdcAy(it;XPlUP>0NhvsD16M%t=8)%F4DO<@R1mzbF;x4)riy+V z8kTS&iW}}+K6kwaNif#Hhg$Yd88;xz5F0M19ATijq8lk`w)@TNJa<<0QDvGJ({joN zYKtpjgILBi$jr19oA^mP_?tlbW0pPsU9@DlN2XhU&WzCd!MOZC)^A+jDPqp+y!#t- zmuYJWOo1j>A@r3Q>ME&avU}pV1aXhYNo;J;R$M>O@u4?#&u5lRHk1_a(WJwEsM{wy zr>DKX7yQ{o|N4$GT>dW4s6V}zN(B)XE1y=((qzsq4(uroQHa*VSOcRKVYIK|ZVHPI z+xd=Am$7r^DJn%2zC}E*;>pR5{L+%ix*Lfgnz7g;iP>{@u!|cAW%<1F%=CMk-@)Yj zR>w1RFo@EH6cCoysV_Z$xcWwX3&3!KwC$M~?3h57`K z0GCjC)6f^%t7qozSGyxZ>}P{qvai!Sbvg5(%TQk9n|PF96KQ~{P8;{ zoL4(I$ZxLNrT_+)%x{#94l`Vz#Ij=CE9(@1Lk}<;4(fzT1_oN;2uk4)8lWytkQO@B zpwaGRhb`1{)(-6;32zNf(SQU`+)4Ry@@*-i4pLcIsVm>x*Qe|V>W7Afg)Oq}_p3MQ zoN*nu0Q~s&b>E}H?GG=cF(PfzQq#O>>(QVbB4r$I1Tg2xu6_i~oRoeK+lwmL z`^JnAEuEd-x(TDRCq!-mj`sN$m(tF!1DGjVt?vbF>ScFdjrw$*=WLrveksUm98B|3 zHPq!v3_qlw)Y1W%GVFR0f`bTy;d5D1^k*$j+s)EWf6ZgM zy)AsT)&L?|7w|bY6CAkqY;9u&uPIDz`~5C3v_83hI)&J2QCGU~bpb-v3>@=mp2Re} z()Eg>Z@nWtiR)L(00Bvw-YdR4GK=3XBu4YCyeYHanj8ErhE!SEp)7?k??gJe*4U9v zQ;Qe-a34kURFp!g{YIScp}!_49rs>Y_k!@+VoD7DIOvK~{Hgl2cNcHHN=*03#|X(r zLWp?Go?f-h+I$P4S@&13(_EeYOIt&msIwSL1uwhdv+)D%193|qVs{7b=qroEr3IzU ztO#oOl$Cs~*5v!SEKn)7Kd#mGWv5e&8eFci2r}H^0HSQQSTTXlCS!6V_XmWy9Pz&4 zdY?y^1KVti9z0z3vOlQakFwC3ShYxK7k@ueYt^$_pLjm#TDFsv2l=8p=$$FX^BX%y z9U?{jDE$)keLe9@T<_CyLT)cB>+a*#`~!Z~B$-fK@YM^*CA|bkdF@cm8yr$k6oNch zaj*!@^$RaTRjF-djgewyeju)Agd5#Bkpcu{98q>O6oMWM8EEKM2H)&l>UA88FecHX zwK!k2zm+ZyEh=8f*AA%;0RK>ny{C50ar)i<$mVK%jCVo%of|hFcV`VWD3-7gqZv(d zaE0rEw{Nb;le51)7qn=j{_T}DEmSLvNNReZK#vw2HPE%BpAk6vX_iuCgatsg4{ zc@#18_5Ou^NZa%Dj@%qv4bR0k=wp5Xi3RsrC_I z(V$`hBt3NKCAkJ__zBY5Q0cU0URK@$8C3HRY<2jE@?M9+R-XBLO(I9DhV>P8k^M>T zP4%dU{y%4Rj?H`3dmkqkEmtXx_WpP)M~Gc_Qad*=w>wUL@p zKGBPDaS76^3WUP3^ie|z9dpYDz3%50@-OzPUvcj&%Y4MPsLi!F@<-2^hg-P-#-PB>=-U5cOLYw{-khn;DmuzSCgl7uU|6J4v@~h0yi4D1M+Xa1-;Oz zv~f?W;IrbIw+&b}yxJYFU*_dnl9FGKCmnG3#!dW&*1^~tS9dkP9! zF*|3~S(YPPthoTfrlj^5G2Rma+Pkbs>y3d6z@v($l&el)>Q?o6?hcqfGL+qz^zs@_ zrD0cWLxWz|tiSC7f2L409j~-!c>HufygD^e%HsTR)forkDZ>%I`Oduf7cB$_F*)$z z`qSmR#jQI*#Ib{o4*r&Jq?s`mh7b3Ba+thyd-#qQbotL7lf+D={NPD* ztf4e}`8N&jO(wF9tn)M$quV{lw9l{W+ovy&98d@Q^fTDRRh>WrkJ4Bvz&K`=Kd53c z?qvqCKGn#@l`=egqw6Q!GtV}ketTx_-f&^r-dUUaYR3yH#uux#ylF(LZ`+ND;xef; z&o`~cKT(%C*JXei^+{N{9#_U?YGqhng#XV`CEi&n9Q45LL*zTBA>{?)EQ_MkK@$q5 z{p{Oy5lL6$8-FYy&_V_Mdn?t*PRn3W|Di($Exdjd!G5*eoOI5Pl zqqS_l9e9jq^p_e+=Z$>dh97Y8#>#UIOkePA&Y(L>Ig+NYQePt8eSsh%$0^n`})v8I<(-W}bI5L1ue(V3Ni|5C5Bs#q7D&5Sxn=JE4dE95R6e zS27OOD{h&V*f0vHFfO!T*b#55O~&lh=u4T|*0b^L9&Xw_4Nfb+Hw-|BM67O!yIR_8 zhjVuryL4zqfHw`@|Dc-gvEAs#f_`HkL`u^a<}WGPkbeJ$d_&Mu$Syr66uq>anmdlV z{^mfwA7o^1y?JH6Fq!Q1GUGz-Zr#kL#Sl=5?L`~uZoNO^7hCMbm@$Xm4QQZvvHnzR z(5va|bk(P`)!FI9)3*-WCh=ss(Apg@aVioE<`b)*dvhxH_(%S7bd zPfqUk4n0Q&o#9GdcAxu9<1zO~>!H{1Ltsq-0Tcs#IZq6I(#Z!$nTK#X8#QQWpvS{9 z&PD~Jt`pchu_&oHZ=gP-vN^yX{+%`deFDql<1@hT&M00|@<6_072JC&T|Q9gRmoqg z1WKGPl{qZv?<3Km)sM-;gUBz#yQbs5OQg91AX!-2vBBNNMQUzH$HWZUmBXkjUqFx= zP)lj+8UJfom=nUFpYU$yX?YDJJ^5|oO(1<|4Ej~I+MlN*yN5T&#`El-V+odiTdP7b zI;Gv%lr5)-Z(Ch5sq4|r+qZm@4K*Hz8FY(g8pJBRoWEy(&3nL7ZzA*qHT8UXAQ3f) zv#0@-y>F<8*O0K(`4rjLk}eR_{ZcRFCJQck!t-Shy*^%`D9xZ1SnT`_i^0~vh}nF< za}8z?*-2bfN*Gy1Igr_%XEQuU5ABmve|<27yqq(r_*|*Wv2|9JLS@?;UgIDlcXW)f zah@r;nNxZ3k*&(p=j+l?m;CQ(Of=2)xvyG7V-$*wF!yt#hZSxnu*fEN8gIYWzI%7q zr)H(yCpIqZf@L@QeyeqI63gGBw4rx+`%f8k&1J-o15C-XJB`$q)xP0mozEwNnD5TO za<_Vw;d`J8AJ^`R)tS;|o6^eRFE-@y+YeR9Yl0l74)Q!*H zQ2~Cvu7t!&0Dhl9>t~(kY|qrJH^2Eucvs1*j_IU@^}>LXx=L@TnHuYfdE=fs7qMjs z$@Z~(0OM>lh}S08l6h?%90J#K5DP9IOv#g$8%io4Nd9Zd{+i2Ehd`^7u9Rx9ux_;7 zDTaNKQ0<2m!tcenb>vGQit>YuA~t)O#I$&ieFeL0e5(X+g#uUav>W5>DwWALExF~( z(RwH_eZJV%&#jGvwh%vW1e%T+S_Hyjr6;yylRkV69fMa*k7+fN*;G%!kA`_4qc`Jq z%wUNZutZwR?w)=z(961@K}@WD6cJp|pfxNT-pYDmbL615N?kZkt_Z6h?-Rdo|2;yV zXIo)}K-W9dq@}2oJ%H_l`U}NoHd>BnR&T4GGl|J$J3jo7Usk4+lpE+2m<%ehLxb5X zk?qlr!2X0QkVmwwzo9rvT$Cq@d7>?4vb_}pZON|s7OO%aB_wOWQ6%`WmBMVDh!dYm zOs+r*DB@Ha1v*u}oxvIt9pk9a+epk-x9A4OUzqp|*yofwk?%Z*X87s_J zQ*6xNR(Cb(5{OC^@}&IV%!DM&Ok!j943Bj{cKzj~+mx6Gb2mLn z(B4Q`wi)|kCo!-Ny*;5UnGzc8>>ou#pR6ihP=loS!z!lDl#21{-bs&8==E3BZMSbk zHgCOgH~rc}UUBLM zo&VXBR08N6ZM1j)1k?T0Ka?JJaYRS9vq3FB#-v>-_p+|pC*`(GkIbE6hJiem2C0@Y zfHCCxg}QDi_pZZL$v1#9fQbq2_8U-H!b{M#<_bqWcsLC)b|vzY#?V+yR&0FDp1;g3 zpjOZaZlyi_M5f#Q{)oyFVNsyh;?wVGLj#z(e60x9*{|xlIOBMp`RSpbI}CJ@Wt(lX z+ZWhLhmtk#f1Db2JUBjySQ%(7l4>zjApC~iO&-y|f?VlT;2}ko=tv`w@mNGeSCG?U!7I1ZqFLPf=w?!EnFy`JWMJP@< z#C?`{7k8Cd)H5W@Sza4x^5?yw9!j!mtxwdM-c>TGzoY7zks)(?KZ-WD!n-|_?sE^hdF zhr^QSfL^{|Kp#Tl>yloh&!O}>{-M*-9!<3k>%~5A>c3JWL^AKOkRCuA$<<3$nv|EF z+qXS*|1*N&`G(C1?`9uXyG(hA8;Cd*cZ;nWqqe+UtR=MvB<=T1>JYVMj=$T>of-jf zu@2;c7_;lXfq}0qRp;}4Vt9?EE)+;$swMzo>Ae{%_Tsbki-%8mT-(v6bUX0IpN4ej9nv2$nL6*@GZ)U!((R{^*4@numQ=Kd<%h0h(SbZA5`#0oHsr;Jf|GJZqNqC=f@WH;Q)HcnsQZznky@$0KZ+(;wSN1er{Yzu*ye^B7>!9*YcTA``B%ogBYJxV0<_gHyQx-;L*%pIgRxTkLnLer z#ggVam=-&qjDsJ3={1TQewDR!#_gsPJIY=((C2}CeYLW3jO*|e1^fF<`Avwuzp^IxltT8l@q;b1GIOqY z-iYrEt%FLDPIrSdiyyIyIJelALEedkZh-dAnVl!DhMVlxZGODRwZB%vJnDd6VeQLH zvMXl;DsBuJML6c#9~u))L$g~*Rc;J^Fep)MakVGzryHnXY5cp35)q}B5xB#lugBlu z(s6UEb8i`Y&jXWrkf?sBC44DecK*w7*SS-FoiTDH=miEC3d8I4-~2dtWtiBVX{Z7O z3?h_?8c&9Kt}Yi>PEow~+*)~e{+&X$pL}-bsZ<-5Zz%!|emgmL;KQ0~QTT)=W-L6(-7uZSM*hm}4yVM$}EEaBCzbIcW~WX_fN_o(WeqXpBD?i{GSaAG=ZBR5I5@6Ag+|ZHn>8@2R=w=Lww(rAhJ0Uy9eau)Fx;gF!!Fe6+ABnH3ilxeJZ97}WN zFhNnJVXd4f#C%!5nVhcUjmr+Bdz4)9p{_wY5}(5{Xm@`C;?l{UL(AVhkSC8Hi&IrO zke+?9Rnzd)O+r}2L{4W}bsmkdd;$%oM~*>a@Wzlho82qE+`o1iio+!5(EVzAe0N&+ z#Bl8#7ph+kBa8-UL-!IMho_F#%T<|zpUqXvvoL)@N~;b#4u7HCKDT4@OIFc{mw6*F z$ivzWe0|8;I~)q<`BRAK#<_j_&fmX0N)8w!ylt1tPN*-(tk+NS(*_hq4xYRY_;{%QbW?Ys=d0n0m!pH0vlBey zBP@RSqmuiLbmm<~D~tOn_=ClJ!djdw$QecP4Xpr>1e9sC1HAVZPFLw|-xX6mWea+ z$4_eM35FLMW~mOOA*zApSmQiV{eI-C^A&|S_P@HV#x-0-XsUJ+M|jpgu81>AjFXTMIW3HDqte5r2xj)r4$S=cyx2x$VOyg zv(Sn_JC9ud3QWCU^Z5IDO&++4_el8FI1MI+Sz0446r4XHROn6e#_==R2Lfy zEB-Oqy6HXh>ai^v74}Czml(53!$kQF4(wTZW*s{tCmt#;ws$2ImiH*bSg@QDl&@Zn zXF-{Lx;SB871J@c%W(&!rQ3?R6rN{AP}6rK;9(`3itVMR6OC8%Kk~!ti>t!EXGaU2 z>^*ijRg{*rL~(x?_ohu##*kN2+rq`Stj~D}<~%Q2hl@YZ+x9l^gK0C&YFZ7u_5wSy zZMEKtupHiQ4GRtEF0mVmQSB~&N~h*_;D)ktWqDkZRIN1H_>>7oqpDbO?j zuxp#fl^@}v6!W&2(D#jqUJEjtq`QyPtrA6^1qj#r6mR+4qmToXeoBWCY=`61#F zdfOP|U4F358k}xQbnc~S`a<|i(GShmBaF?@7HYHNAcNYhaQPO16=Bx)kz(b4v<~#x z+RMZJ1&<%)=5C2rP%3<;%;?i4#TG81)9@i%-06vCJDs0*hXM^38lncL3=nO2(SL2$ zfoLDgc7RpbvTf%d|3jsUqDp&I&QfjTGp!!4j!UJ;e5=#n##&l5>IYxw^Y*mBO;Ti> z?UAq)*=TQ3MgNJK7Z;a~Xry;be2rdP%D??8W-7!q!X3tEeXIkEkLvZ6bSnl>Mq|cX z!ezE1g&XAkxZ&AJf_n_DLG%S@DL|y9QDyHxWr)ib$?%lN+K0mfv-<{^0eM_uNT=Im zG_{fmGc>S1cJZ5QEF1AL`}FmdQT@JxZZ|1w|5|Oq7v>Ar)RWNkNmNYdE!InA38=c)?P+hhmn=a z2Mx*k#xA0()!2X1%($4HcT~RNvu_p32iv*|e!XtVgEx^FX5KR&^0ifL%i5yRGykQ9 za@0vg9zL6U;!<5jDQ-CJr%?Iequ&#|is<|Hlg2ST$hMN^X4_I2?bT9k22|p{TE(Ln*zAsj{k?wZsI(-d&K=}$+tZF zZ`~Fe?crdO{ks=7uXvOL=rDg9oXYMi-v;<$;uGsX&4AhNkhzR<9%5dkIhh)jtrew= zXoBc3CtW0%NN0QC%IlQzw&J)s$GD>ZR2;_>ic24yi^ZWt0Eh53@TzrY8-GI0lE|qF!ZpdmuPP+HW1t`kb>0`yh~8~5MO}dv@bcar~g!G z+;J79jqDKd@agpkaq8Zx)eVCuD?8>P0w)pO4G$iU{||vgAq=nn14+Lwt+S@i|7Y=3 zsmO)+&*EP$?|+s)D6v{P@}I>^ga0dkLbR;pKkJBE_yhS*RT6#6I`98I^uGz~e<^9s z02PHr{M-Hibs81YzCNF`6VV{{`#8(rA5W?LuMj~m`X{q&+Vp<^G9AUu8{!aP)4YAb z%SZo*mNoR&_(w*D2Qf1f9xQ`$21@vW^Xs#zuBHF^&i{wae{0kC_Ww_z{!JX4{(nPV z6TgjOMg_L9=Bbovm!P8bu;}#(285>}4EiffxbfM8-%7!9pLk4QVECYop4BAma`}Jx zY1qc!sP#e2!Y(BLI(G!N-bpzRWZF|q`b&SL8n2I0DNK)8UU#C$bq_Y(5wFUK(wl?3 zTg`P?P&!F#eH2sSl&*5rForB9aOO@jgf%oCgJ(oK`Tue8Z(YA&QtXVfux|C4a7GL- zE9HJoxZXW^70BI%yb2Vg!H)AMkn35ipJb61>ollBap)w+AImMr6JUHoA?zm=tHYl~ zwIc)%0mA&%0Wpjrv=cw?4kJ0j&O&E@y?G91 zU3OpFPh)ig;+qXMl2}B+_f<9FNI{D5`#4WmI0el4S92o{i9DF4$yjC|6Bg9A zd`0AUHx0y#Ne%RBU~@$lpHt}Q4pC}fP4!zcjN-Ehcz;xT<}c$MDC(Z^Cs|dIc_<|g zsWVXu?_3(DVsr3i5VDp-6s;_GA^3_4X-HMtMyY)es%Rnx{V_wg%@hKzt0sMk_;8*R*@+BjUDQh zc$NW8`5ie<{|Pg9OI_e7pv*vzBZcr&$VI?Ws zPK6?53;8K{*iyb!k#M%eI1R&QY~1B$lQvohm^1#Eg?K#4m_L?74laBRh*yH~)^BUXz z4z<0CV>!ZD_kTr5#2_Md%KD{mO7ujLH?C~F{H%PlQHapq24@E3eqWvHi2ul68pXx2 ziyt7Gg%s{D@BI4TK@5z@i>3@YdRUH2QDyurp_n{D_p^VK;&SXFb}fI^0>rEMIANd#t-GnQqI#~ zeJQkpD9q-JR{d`d8xKORJ;SEP%_|G($(`oP93EHuzr;*ffeW$YQ(Zx ztE9D0!h75$o`X%z0ue@myj|FA z!8gGAu77#8Q<(j+pLUULA7xruZ8j&r-Mpioy}&P@ic`wVn8Vcx`%gLpIwiC+La!+*%w zXs1MO43n~d;Q&sFflUFgYhYJHx!-ueH^wW|QYDFVp3y?F$w&do7`w4zLFtGWqcn)j z4L?2zdZwLQ4zK|5r(*CVZVb$TpM_mJj0XyUTpGnXmc%I{@eN>R(M*xWK=LeL=lH$C z57;*trj*EQC;?y$_%ld8X7$+mC(_zYO3DUOuzsJYvbsp((E(OV{#`1I3^Tz3$#RoW zJ0^0A^koP~YU8k#?bVC6`>*b)aNWtq<*S(;L~Yr;@WtE1@8BPXr^T=OKe?2DyK=`V z=YyrU$}9h{d4G6^jmFzOV?E0bJK$XLWVB#s0;9dVe4W(5ht6 zYGA*S>0Er9hcblu)r)uT*@!Xm5Y9KHt$*lt_qrr?A;l>DWJx6=V=bUnRy7bJCtPd7?WR05>*@`JB@$KKJYz zHglsKm8J{VNb|F{gh#r=EESqzZ_=SF&vGN_kkExe$5cqiw$!|gq7*WUfjOR+<9;d$ zIH77GU_SYg7k0_{hwHJ#)2Dyn>f$sU8-p~20vzn_;L_eyB06a!toLLK4;FW&C~K0A4K*B(iHwWq1*T<7tgX7!WqS|%0`Knso@P$lrf;9m1w-=@-$rqG=1TelK! zA^(yWYbyP>YX5aAs0kYKxZ4G@{*qvsbN9o~b1Nfw>)v?Iq^eqN&b5M+*!6zU*roeJ z2G(|$Q~by7&!L+ZAj|alnJeFmjqKW}Zx1leq&+WCUfoo>SdoxQ)VBzA@ivDitDTTh z@=m-vv>TajQih(MX82lx5 z-`M<(;Hir(b)-#Mdc19r0(-G_q;}9X2OLr9=FzC0-P88dQ${Vlc$DC-#LMxbfIlKh>M z?S2MQr%ZL{>O%V@vkVK)-X2M07|LiK?F|_CddcX|{}Odu#QF%Pp&*xrQTqSk>#gIW?AEqnm6SFBLAsB_mz(MKLC=e7YE;@*B=mFo-M^E3(wFCF>E3E0dJ#T9Il0p7 z@nePk|3o7S3OKFqO(E>6=XU<n-F^->UI8Kxp;(oD(E>2pknNoi@V1_OLl#I?QUE zit-$}H}AvO*k$<6f+K9tz6{^oa=0J)ubvbM!3+*b-O@Q0v}g-_vzUuOf^={}FTJ!G zJni;7dq>!xw>$u)Ia#5qDYyhO1bx}r^@XVl&edub-kl_$Y>*nnYA*ft3Y%7yLfw(CWs1yV|Dhz$Y5|=u6liBV0Z0;rV+3+i&!h(4P_WZL> z@=s5?R8m5bwN2t$@+0Zuh$peBK)P-G=;E9L4mPSs>Hv`=|2Kr$@-6? z8}Qi99Gm@b3Id-#BRa1O;;UJGv3!YIv+)K~xhutRytoMtT}R#exGW$)?8NtNs4bpu ztPi%R+#DJ2z<%?^wL{?f>pVpTC!?z1$wMZ`>oWWN1~1B9T*INI7m3&Po{5Q;C&A}; zPNM>vQNGZ`$x>}yK{(9mYHbXE{QDx9EyvZ6NBt^tvP@qJ@8DKXQ2P`VNB`9o37J*9 zCubPPA@~t1%=%Uyh=|gljsvJ~Z7m_PH{PlVDiJygxz>9+(Q($1k<7Hc=mm|`h6y}o z{vl=)^!2{8b$>{8lGs!mA8IZdC(|pIjv*aM)MlL~j?ZBPg6Z>Y4ojNtApH!jX5LG0 zf!0P$!VpUhq=wa2W#*r3KbJKwhf@aZzrHR&!D2{uEjRX&T=cf>WDSb_6|q`}(dKG5 z#x|W?qLCfhVyg*RBS4dSu)24ua=_kr6-#28ITZ$^aayB2lPJ=t&~ZH3kRkuSrvGi@ z;+PM8qaGX1z{Fxp{u&PT9p4M(?w?-d+Xz4=i1R+~J=w_}1;ZjF$Eg@p5AU+!u?o74 zGKvykh^`?9+OFGm<#ccrdaJJ(mUksYCE8NsgXaTZR5?um$U?_Qce4D#aG+;Kk44vY zKSm5VX<|9+b9Hk0X%<$+R0G=2$)CdEfkI`PzlnLe@9z{9z$3W_NjE{{2vUo=3i<`- z((xvZ#_L&rTct{GdpbQgkr7$R^DVoJy>^xx#g5#b1#s^C@{8d>)Pq7My14W(A@w0f z#vU|LhfJA#T-Y9ve1aiUAT>Si!O`RV^tre!WqQ)`4+ z3?cYCZ0_{2L1x<{&)c=v3S`*P0!5KStxT_DG#aKI>!#(v#04VgQrP(l)uj`Utq^1y3` zq#?g&7XyAbkod;C>xRj4b-66~;(FYoc?|4yDD6b!7tMIBC%2_eRS2V-Z=k$kt-_tk zNh0GrHysUM1G?5IZ_2GreLA7byNiOhZ+cPL@94I;TZ9LP81jE#&4Hxo^ED1y9A^uX z2aqt?HwMp%^L;!Jc=QaI;k+l2L~|Y5al}s&HMF06#~CZAao9=ni=hwV#O-jYVmrgY zp$hS1bt-=Gqy>+$mZcF%4#7~&O||P(EFss#4O2u3b%QOPuZouT^DwKshw%!BiE9+o);PuuLba>^<8vScMeHVulD4a7*PeC6fGFNfzf3 z+fgQL^^s9yRfC=UzhgM+B9F|-%Qa=Zpru4~UTsyP(W1GW*?YuRw)4UsGmSea!TqVf zXK}I_?ab3TG4)DX1gBzxSN@I<_DxOTZEt|eSNvS`c!V$7A znp!H(?KK7!QTO!5HW0 zl2i>b$tX`Xn)m56Ec|a3Br#j1mWBtD3?sayJ5=*j6xDsGiT7q=yq&EFkY<*suCA`e zfwsYcfhtAIWi>iOB0)x}XkR*((QFpWxtN({9mZ^*^VAG}XW5^SIcj`82miCZ38{0u z{dfZ)CR@V|s4g}*6HS61u?F$}nj*QJ2Y{lBv6(>YmaJVFovn;+?Ywe#YNpT3FR7Em*)!DsXZ|Kj4{T%p$I#L6V zv(f;ax2+}8gfAsjNr|Px-xIKn{q0&*DP5ydZ1iMXEVNY0zcbmlUH^MXKf(v$FDWjL znJ9WMM|I>L^h4F`oIR<+2C~QnxCWv}W0*jiL;$*rj7Vh_!5c}X99njl zLdI&<^|{%uGMTF#?SD_|p+rK;ZQ!!MM8^W(;dH;7Edu|5-|B049Y-#}CUQ?!5U>Zs zeSOqPuA$;Q9ZMHA^ld-H6Xq{SCWx^Kxs3t?Tr~w8#9ZfE)+Gk{#u1q?P zR+zGn(E<4g%(ibWpFp{be%O;_wb5?up@M7B4+w!Q1*FBm1M?fGElaG$997S;XGNF( zYp%nmJPIK^6Fx-e0k<&H{qxf(+5xRdoa z8v|Qe@!WT=sgts0)LS#7F<=Ibfhc`anQQl*xZKD$lmcRGg!yudbI#zgT)-9}(fKEP z_8UW#hJ!n*sOxi7TayBsNo^oSMRlU*LbKJD_WhysXBfHaFQm4H#NJ{dIdv1Z)H}@L zrSfdG`}wg5F)XR$9kn@0U66lJ#QYwVQQ_g+T3oba)afV{qX87n!B2AaBo~RBu#7U@ zEe&GD5mvp;0GRQN8^^~iljebmmikydRsLFH2hrSKQ7`KI7` zW>m43X)X#XU$wFm9lE~QA#*ZhL3`Dw>a-N!eEK!NZ^|~mkJFaA%Cyjg`}okKJ+4Nq z#(3Rewqq|Rfs}_CSL!{Yf)hY(MEx|q&ETvXltX0^n|*~777S@*mSZHXmG1t-iiKEw zAmpIMLaFX&K>y0o6JNX8!&A8F)nHSR#sx)%({xLqqh9rApopqaEzW+J*>726gH*7d z7!Y#X0nzum1gMMVewzc>tRnO##+Ph`nvzm%aA=6w7kLOLn-XsEr#d&|-KXwP7I@Rk z;mj@4@MIYIxGjB>z?D?~yc(iytZ#td8 z8;ERAM2Mr}B5%!&kf+J-8dDW*Z8{!p1@O0U!l5K=ctLx+isO7;Y{c2;*`qEY=oU~} zC$%_R4Z#oYv=l9Tvpp3Bc(%G_XJIS{w`EI7!{L9?OaoDit>8b&eN0BgE+_^6&uDbSNudtvbXW+ieLhMf~Gw!j;_V z*RwGm7T|QM0#PQ*l`Fp?l;~8@?1ZA-K(brMg?7|Jt;kg5!Imw5I3g&Z$_N4-b)$o8 zM+MPeV+F9j3c6-}`NKDYmG_N^fE$abcfVo87;$-ckzyv=)e=xv?e2Z3&{^QTQlOew zJ0Z1GjVJvt?A}0`if6thoEWzM!hQeur|asIua3=Be7Z~h5Ng-EeRHo0&Z<1;vPY9ma;I0we-gHHcC)ry4U+NWz04AFG)XBus}cB7llgGN!meD&(W5 zm@P=~v#SE~@g|3hUXClV%xH2!^mmAQQKvO)?i3;fFY%3)q3wb3ND z4YbV!lwH=%1@8^rJx0P$cFePfvf`dMUyXE~G&bI8dgwVt@}KXZt)9Nw5j$cy>B2gnmM33;E|;py0)5 zZx844_B8FPQMd-tqh5$UBHTpsSHHb+sU~Jw;ycP}e!Ob$CtRJiIKO-92Wc4Tk*lgo zRxfi6TRwwKh|r`D;+gtYGkv_SFr9AxcnOa1s~Y$Uo@!Qgx;@qU3E%?c_9#aMT-4uU zVMN_f3{+7ucilZnT3jgtFUbcUwqyi&7)Max3YMv#Uvd@bP6z%PACW9SG!7w&@=0W}Vqpd)fT(4(5@yUlk&M;;oKkLhy&*Y2$k1hD9 z^dGu{ESsg}x2>=08dlL0juJQLY&Tyl9Tgf$`x$`Sy!1gA-m@Ln$wWXUvscxuVK(fe znACPs3Xnmv1YXPSaqgcAU)o*^Gh2TuSs3Rt6cqB3ejUx#Jz;rr*8-B+8`43mB=R^; z)XaxR`%u03Dag1CnG$2}IHDM6*``S4+>&U%D=j-)VGk;IzCHxAdCtWHEEa=1Ae6D1 z#zo*b01N0OKsLncG~%hULUw7hI?g1LYc7W3{JZC;Xt0R7q_PGo)!s~F`<-wOen9b8 zuEXDjzVDTa@wb}6^7ZRUlA|U2q@mpaIQqv}%9OBJJVp+iD zIvbwi&=D<>#UhH++FNe?*m(-%n;EzSK?=feoQA}CdiIT`a?{X@yz(;LZ2~eXhcIek zdw_LP2k#{~-wG3V)r6frtAa*8NZzpE0n`Wn@o@Oo^O$DoOVtO4C#nm!e-TA0>;JR0swoS?P$yIn!}6<+s<60$`4xz^GQ z*M3vO0VBGb;HS^_B_lZHp&n*jmS)EN&b{<}>_?~5;DiV_&CN_&q#a#V{zZ7X~2qvM$dPM?&WCoj|BZ(|n-sDxF;}Aye@1lyDUl*>% zqz9zmC(m(O$<;FO4#raAp3EPwpFvpWF8zrri(~ju&XTdYY{vt~<8Ys3A}`%IPB|f_ zw{uiUlUAyzxX`Zfbmt5k>l$d)d$iiHBLzF}{L#a6825DCbF!06bzzRVBb=@LMOL`z&LEdD`ZX#{TEjsPV^t}LhAoJ{jH`zY)6*>*$ z1~*k34VIKr@3Ue~cc&9UzSYXSUKeo79&Fi2oqBKvuk%K0vwO`|kMBTio)q{SI!glb zRwe^{sa6xqdbE~}9h~8@C7s!_)qnZMhv5YYAtijFMq-@GJ#ZA~=OoA;McW8%D2=a5 z8r#J2xrN53v!HjTm_)Uzb)TvPF+;`$4~UVnA9s%qcbO}y5q)}#&6kOk0^MKIpc$nt z_vkR5Fqp0W6uo{`{LWF2;J{Dp=gGNOA0`6k`v#hgg|1M>KfzcQ#!yWuVM1d#k zq9L}k@ZDXQbvmCQSmko-rrXB_$ZVB8^B929{$xuk;7md9(pOCBdt6M4s(_9JA$1$o zlQGS!b2d%Xz>7s}GoIaO7{(|TD}DiFqfal*LLlN-=X>)a*;stj&K!w7+YjPqDdj&e z_!v(lb3y}??jRfsLJ8Haix;|E?mLmVB9ELLFabI zJa1H^4uQnH1-Y}Yu;-p_FVU><9YLzUSA}AR(J!gf0Du|m)pWD!Y0d?7@@MoFyAcdE zrv_b!Jz!-x`z^=}WmOFU;tez{&3h~Tl=n~tIP0l%cG@x-_GCGZYv@i+hQ{_cT5Mdz zV)tbz%;mDC9%N_Cde{QQ>63t|m8&l??`zmu4Sp13@Z!pEEh-A4?qO1qpW?LEZq z;Z6BgfsML6yN|@IPY?lRYSG1836o*TnbpRD_<>bZqx|#oYi)9x2Yi!Ff=jUNg$-Yx z@>?!kKA{8Ni<}K@mC(tbiG7pY&Tu1(-4EWW-?&WcrAS2-j%rmg@f0C*PF&ulkTiqBrbbVCURO0mQaEno7}>Qc$mf|J?~Dk;om~DFyX(k z!5}G6TsKrgrO`!S0I|ZmRgb4WFKOe}BqKi{H?U=URYSzzj0NMVM-?X(rm;M#6CqH| z3+O!+v3i9aP>VBWf;Glgi#{OgFj3rEl_&!gEg|G&^zf*yja=gypuyo6g6KD#mU`p$ zB|pn2@=^d%6Zmr(z}~lQ*E$@lQ0u?V8JkQisk&1djg1j|CRElq7F zzqHk^I?^uNwhnDn0hX4`xE%b5xAp2r%~P~D8E1v^ui~pf$T!#t3}TNT&grbEw8PiyIGV_r>dAb*;pqQ zTPEi{rnt7G<=E^^0}9pUn`D4t&||i7>mcIsQTwSkVUT8cLn(ucDqDk`Mm}r>R6ZVB z@dTpdI4-7GSUt<}<}X8FSV6qxv_s_^o#dvpc%qZ^QCTsmNq+T!QvST?RQ0G^zoBY0 z)uokW!!*Pao!iISh)}dlG*xg_L!kPXj)onm50kO#o=^ymh3-vsO}$fFH9)oN>4_o< zD`et!+Qv(ITi9m}xG0)i6hyDtqxB53=OsuPY}BMa=PFSXK@&BSOsPY_G&W5hnBEcz zMO{bjZDG#K!fM%?C*wo>^Y$|0?-)kQ^KXxTe-IW%YcM{(u~v3HST$}nKs<`ye-+6b zGR>{q`^S1%a{(W~aY zu}nGlS3yCTGVElN^zAYp8nizcZ|96W27j^KpKY)Bf!+-UXa>qy zN1a9}^k)r8@JGbMU|sVE226XEPt501uJYiY9u8?MvC3h!UJjSm1YB27W$aVP@eL=n z1aDw5db14$3ql);%~b3BmPwg(p;(&z=>Y%8y?oQEm*W1tu6>`4$7{bhW0EA2kShTW zGmrLavM!n|QI|4E5fsZ;*@%SemkU&pa{`W&27-$z`Z()x+0WAmwVoC^I{o})IRz2q z*@7|V+T%h5X@RziJrN_LpbVa;mR~nL+hEK=ZN>{B`!tx;ji!ZLr$)C~S_xD44Q!Wx zW&pk=g;A|D{Y8OkXo1^ImtT$0i{hjv2POeG#j+Q)e2ir#g{AY&73|b}wZ>}B2&ska*3f(wu(`!==@ds`)W9ruzGu-mn9*m~sJEVt__dO_=9%jXA(poHAdD1=^fowL;37bIJx9jCN`mG>K2`s{zwzjDpTBZAm=org8r zLl1lUJHPM1(c{YcWVgL>C@*|D{=Lwx_~3hQ%00L$4L&JMyo1L>iy5+@?ou^NRbYB! z+Lsl*v0JGrBN>RSQgZ8RoF`dhCl=dgs77TE0_jZO=1F(FgOw1$)?UokyGG~BD3s`y zHSiyo8A>0{7)qD<KgZ0DJ7&LQ|EFSXA=avL0XWBKYDvN}4L zC7N*ltKM}`Ea6Gb#{)wv0rd9pfsq@swdmjD4 zHa{ys{zpVbt#xb0RB#t9CD(p|H*gWUNGoADov3|^H<%Imx}atpm8S>(Mel0yyyjy4 zIdI=z0U$1u0^~9F(D6xLP3s!v0hEIWlHs&b`4|B##l(_;ZtX>xtmj)c*;-tJLmfC? z)5GR!pgeU7^m76o9J&uH>~E8u|D{jvUnOI9f6F;u3GAAo1mqJ8TRGGt;(44bI5xf#7G&i7v-|nNAEa&(W@#>ND@F-BhLtf`=FIE*;$A2zKq#3WX z?#P%qV~}Q$p*G?=6~{N$+){tkd90nF9w4h@4$<7LbLjQ zuqulQ5`k?D*&!^H_N>e)rR$3WvWFI(!0Sd6|8PcskNb;8ezk}*@7zrI8COJ;CJw5; z5g)gbt#I12hEL*sGbuphM+nNoZF5M*d9d@!R>uG6`_D_%t2$6g#OVf61@6nzf18NT zKLR#!@lVO|Q_>+=yA(j1)6VEKx9M8XN}$$|{Clzh$l&}({1Fzmh9zSDLUQZhOjMne zGw9(D_{TBr&;Q5N9)1V$w|)O;T@Psq3W~2h|L7hM))E*h5C1>D)xXX7LsXafzfIw@T_EqdgV|g@!`gi1U!qd&75UKc{`=J2E0Tc!q+DMISusEPAd)-Gpht--)lp6; zXn#fM?zU|krwrG77$N@e6i&)2_+<07JcV5*(DU`viDc|M?_&R2S|1HD;L8>3XoE_$ z?Cxe?Hm^0HfP1ePo`{a-z_yb;$O!+Mk}{)0`c26F%>Uc3`8KKHxWZ0%y`^~k9pAEkmGNM5(vxdE_0%h*7LJ|T-@2(1g4qCj<-(i%#6D7zI8*Ln2mdXVAOlimbEFi z2KL+LMw7{==C^PX;2VE4QMqrfqy>`?mplAIVFT7i8|3c!=YkT)_OjD!pm?;E@UOLw zy%-6~YS)H(?T^j>SLabd>5jtT500VY2d*4vm=8CTp;BAlb=LQkdEW?uhdj!Ea=^~8 zyr_peIa#R?^|`sG{ztqOFITyTo?{vZUgPk(s2^U|7Ds#Mse9UGtGmc!eFVE*8U(vT zdIP0jq4LdguYI|tvL(VMNxKnejoVN~hb$fa&t`t|ZFaow-Kn#k5^OaZ;MG1J!MnYx z@_j2Eg4rQLk&BXSd0GHnYGM z&dla<4*T(>aP*QyemOuWD$?S%%I;qJwfOVncRMvec&bUU{9=exhoGEeLl#PcBLK!q z393@}DVm=XXreIQ!5oPNv)tW_3!XZu$SXGd>q?T8&s_s4XpHCRVk z@Lmq?BQcC{-0}EH7Of(@@{kn2YqUFcNj)Eb{kUf==629t3jJAgeAxO+iqekqT=R*| ztSi2$?oqdLQSoEHhU{!XHcE?2_H{{V#p&QU#y@v5e+QQV3-IoNhj|ZX`nd)s5Y_v! zLjU!lBTZXzpKbh;kX+w%lFmsQsfB9dWG;TSm6;1q{^yfLSdYbzF$8-q$_f#>lwuJr zd#$soGa??*^`wF~6^>G^1grUb=y;Br&stBP(oNktqh*V1PX_evojs~GFn;obgz%z< z1kWsFE0(cJd3|#bFl~eo+}n@l{iDO~P}?ggWE06pQWp;w*DwU*n!V=?i{R?U&zRN_ zF{K%E!LgOOY;aU3S(I)OuB}w8FA=!j0O_m4nA)7u$yOTS;pT3*9sbb=uo16ene&C( zKOVcfD8ZGmhevOgc_LTMu~Oz2Fo2E=X=nAeJtL*m9HzL^>|0ZCIl6cP8xZ4OB5eQB z`S4Wm_2i9Ji5-0uNjx;Y5nbZFdX!`s{;Zf^-!&lPLi3`bC!!yJ{2_0YTu2q1<88OS zSjrjY9*R&vQ5(M43$`wBI6#R)7;SO3U_hw1Rfm*Sj`aX|4~EsJJAGiq=Dh#rB;Jjr z2!|T2yTP%}L!a0;`{oPh+5Y@$3BJ$IkGK?$>zeODrHw;PnAfH6;s|Z4ZQxY@8{)dJ z3dB6N>H)x{b7ODAdvve3LLMc~u&LIhb3Fel57bx$T<6Z-+S)rk<3~U@d{|h&kekz_ zu&%2w<9hw+nMQavF-yr{H20?;_0LJIhPp9kE{+L7+uv;lSRB*zaxRq7(O@2~wRGJ$7eebl>GZ*k@jO@qgGv}+xmulOiIx?jgsg$n`11!h0L zHiMbQ3yv6@pO9q4DeZPVWO z5#3%^F1}(d&);X4F-7I~{BW3F$=gP8gt7WWpDzfmEc_CSm%3_MkMT-V|Jivvsn6MW zlG1qPY!Oej_MAiWNul>;@YUB{-}NDLZ#Bc>zD#(8dn1ebFNApFNOTi6^oF}Wr(^1# z2@6x1=`UgFZv$J`_YrEJ?YohX{+;a9DYqw2$J;2hn?BdFi8CbO_;GEVGmoF{a&_#| za=1(80?3@|Y${ zSLphkMOw>u!|*p+4IB8VlqYQY3~@N@>f37hk2QX8yX%MMSS~i?QFW75tg!VqwQ1A{ zz0)giTWfMdTGg5c^ktD?`WNbc2?V=DLFg7@+dBQ0tsP>MT_2aD%Gx7TOv)l)w3s6G`~XGa46?QsZXm<$T-}Uhj;54;DuN*E-B5<*b%X z?;o{cb-=EX!LC;oit2Ar^VnJ9M|3j(!iZM{*8-31-4tH(w64@jKLI(;bG-PDhzj`o zSE|qScxoa#s9IkcrR4-F;}EiC6yuNP8Q!o8s=H|&M|rQ|BC6*`=RrO92N82MOCQk* zhv5naUYoVyLv30pXfYv}nu@3egVQ9_qm^#1;d|gM8U}WOXIW{E$uNhTjvUj#ogY2L?_)(5v+fq2gRS!* zpn+OwVi>Kq!uUvZjy~aiHv(L9O424Mi(m`W;p6j=>}Lg7_ds2Fa8P-{zZkatRt9$) z!V_z@`!czgx$5<#6t#racq)(p|~AbDD0tGBE`bbD9;lF!=!F~?&N&5M zDL3O^?1&R?1Cb`EuLhu{n^C%d+`*N^j)`dQtZ*iZW48 zo!+JJbpFgid-+!JE-}GdhZ7_F<0U}>uli!&a_JF!5V4M!$15L6pCYv6nzBZ0iyM?v z!N66Lmkhw+vk;4((THk7gW`?hX?@QE{jyE<(a0lqL=9cB(dy;Tj-m1ZL@z`WU_ZM2 zyPl%0C+8mmx@O2qfa4j70L?GQZ_H~p;@()=gH!l);=`euxIZ4_;>)8p!)z=zb zLuQ)JU+0>4T6cU2m<|3+K4$rcn7auLx4TJA6zR1;{b#Fmg=$SkXiKH{*k`g=XxP>c zn(ufNSjINVtL5chK9-9`Qx`;~apG%tSqS=A0XIK#2-*rx$3v7~6+l%SvYgW@lNza1 z9$k_XBfLpl(h1Z;% zJ!GgILk>6^}$oh;nw^|upU>E z!~pz|ZAh0VX7LapI1N^R_dPBj0RqBI?Wfe4zXA=n=;G0whkp9*oV|gn^h*qXLk&s4 zgxA{)$rY$VV%5sD`js|$m-4W{(X%6l;GM4y`3@&KC@4IMBu9sH^WS_A>%48tLQV1M ziH0zs1(VPBL#|opjA?PZ3(XXX*Di0zz@EFpoI&T>MJyR+3W0kSoH;{-l^vlvT=b=5 zEJ2PyNo=stdA4F~+Q_`>sSc5H(9Pc$J;vbq>ge(uHOwP7ZCX01{;`PXAfyFO)A!eA z)AxNo#Vk8R-m>W9NnO)Q!%>d=D@!TI(dwQ0uXnO95SvW|6oI+1vCLMq<5YtCFFA=A z)y!=t`&^hHJ*9 z7gKE33#edgQ~_Ps@H~cq{boGn^z;e4b8S#CXP=JZ0ug90f_;Qyh0hPhr_Q!W4J#G++zjD zo?n<%zxzVD+h`nrG9NL-DdlDq9wG#u%ps!)k$*1T5caB4J+OL_A56y3Xsj`-@bPuV zOM3ZAH}mZr9&WWYJ%OnnA`%4s)qjv>}$nPQDJb22?|YXGYD` zU0se^ctDL$4}{=Fv7X9A<+&a-+uuNg8g(;M?b((^?N0?BHQO0;gI2j4Zl1aAFa0F< zNQ~ALs8(1kw0dJd#+7#~cs63$LXA)mvvN<%=}oiZ0s-}CrSFKnb!4tMFg%;U5Z4Q@ zbe(G{@SmO4+-JRTNieV7KIhzrVNWoypP}@6$9X%|ADqf zVFvSS{6HWITuiK7SF~djv*vmTA!0=NoTh{9f0*yC7W`si;4o4hnGxoe+wYUnQ-O zCJ}9X%BL0?$2Zi2t1Q1-48y{<00DU$C_J-Qq4x!#U`bvu;w6SB_o|m1l(k++AT%}kG7y@~_oeGPZ z!Dp;z5wH=3_WF?Qw`UO_e(4G2J&o_O|KgnP8ss(F)?F`io8BXLUsUlQrPQ`+&mqCt zU=d-@k>-gJxm|WIa_aVZQI3j?p z);F5o#X;8+=xylLj^adcE!3VON;pj&3u6yP*_BnU5ely<{|e zah8_dV_X=~CN>yN6yIG>8k8Zq9z@C;wf6=YaFeN^^cJCQ8`_uMxNd9dalz>x*86+i z2kg%u8!Mpdcz_%8pnlr2nC4FcM&pNAtnogj45!*&q#iWU2TlJOd9!XGsYN?ir!Vx| zx@f~Dg}^79$*}hKowts*{d~Pb4~9$07!~_kg;$6>E1Q zw3FG3`Au2u`VKnMdOC-b`;^mUGoV3-C65i*0Kvfo5c&5;pVdr*-g|0JM4GahC?)&( zaUmAtezqcy{ZswPzS9Y@jz^zF$zvtPMet_c)Ji|gWoRF`S43{~aHNv`siuAVWt5Uq z)iX771D0w=CtdR$Xue!u|DYhA5}w(nWskM5w{K`dLgrJe{pF&-v!;-lYn*4wXAwuW z>AqYN^X9(g*tM;xnOAe#2vxTcd!9+Y7MRz?2uJ zzzy~7!)jNcbuR86g%Np}b$(7xSR`!7J8$eF+j@J(D0xl{llOs6W^Zs~-v)`03$7I& zu8Y5$b``2R71yxat(fqZ(Rb-5W2`-M^#3hm74>`JJO1ziEU zDN(V2!xe(n5^werd6JZ!Q8j^`cNYqoC*N?@+G7%Am-Qs;-z&jiKHcC`>y9)`vi%MJ zvdP!Rb$>-lmha_Ao`=@_{e=k?>90oa#kLc)O6!{md#RlnG|}Qc1os|m3iFdWj#^AX zgrIDIvLEI;L-&`I6iy=$&Fn_v@~1bknm>R3g1IQ}$)=u|ll23Y+_n?2o#-WrD}sg^Sa&G|zYX&)~dC_G62DCIG^i@>!48V{zE zfw!&(eZZ)P0sb8~V862s#5Y7!H>JlGrfs&Nyq6g3Klx$T_<=Ubbkm@nQ6v-(@-s%Y zSFZ|}5BZ)oak)<4id5yciP|z4tpSWR(#R~*la`9t#rC&{X*AP2nR!!EZ*qf9ard}I zi9f1K-P*0RJ3$>>5$34y?jUA#uv2eQaT8R0kIi#$@dQ09)Mw9P#ZU#(8@(!Q7H_{V zoYc~Jym1kdvvCgE zSXBd@6MSyxY=60gh=oaAp8}u3RRSwQ$eJ6?u<^^^P?{!$bTlWVR% z$pom0Zx{z(6XK6ki|F*ok_~}Q!%7r2@bYm+-ig>ByeA23NFoZC9RPwNPJGK7=+f$5 zI1DuUHW}+L-JfK@vB6iAnI*qnts^0;8!8q`F>?ylcypv}t+gO$9yqxmT%F8=flj=N zql1T;@VJl~Xo5UI=o#sD727t$C(g0Qn#f|{kt68u$j)CqU+@$WUw zZT_l&7hVIeWUIGRkI4~6jtI2^k!YLAVT^fQ?rgMhdSo(Xtv?;c^EOKc>kxc&G*dup z1VAq*5u`NgJCLd*Mx&C={y(PPGAhbw?H^Whq(h`zX-R3222mu0A*7|dhmcNb6(oeA zC5En{yCkGx=+2?L;k`M}de8a$fzPfr``-JyewjRRf+w0|t~VTv{fuy>YnbmVNCLIU z1oodZ7mCeSW7Q%E%ox6bjssRMi=bK)nn^#sB1^=%WG`k*9#%qe!Zfxf%R%U~OP`Qc zR8IH*9lwZI!J5&@-Wy)6fHl0oQ|;>Ke5a@7FLLP=U=sfzIi>c{O#Ko}k7G48g+P`5 zK>+(@@Q?~a6srn=;Ex$yonA8pUb(+RfruP%n=v51!fe_ssC=pcB6In&k?LM}zmLcZ z${yx(mG?n*U7QZ)ZM5LAWX;+EX!AzBUHX1&^eW6KBRO2NON zBgrov&8;8P++yeW{RfRI_~=hgUeAG7nJT@ZxqaVLjZC8-lH!giW?_eXd2KG4M#5QX z)A}_v0FipyV)Of+hJ?|>w)LZa^|n>^FQ=F)bu=w{x&oa$s2SbC%-|J&EZJ!OcRb|?yhRzt*0bdk&>cY&@%vQ@csWk15 zN%7_BuxPPCFp<^WuAjP~-3$uqRO+}VSUX4m`)9YZ2g$lU8@bP4Q^z30z)^T__b7(Q zD#NNK{<1*;g)Q3%BHgjPx^q|SX>$+=il!J00k2=Q!c4t=R1_IM-!EHiz0-4EBA&h; z>4}kuQ+p8W?X?9cSpGx}Ub8i7=`~ra>Ab!@emHJZy2exK0 zS|AUN{Loj4ae;)C2|GQuB@78fiGcJ1K75qdbIJ--PY?#$W2S`DZ0%G~lizQ?W z`nH&j%;yfrh6F2_85sOh0F}UTnARfR6^)*#1)4~7^MO3MOL}DnPhr%l*Gl!s#p0Tf z7@LNrrU4*QA$YM~4dBGXK~;_1e!cY>#vprX$zNw8eE=7D{_+xMlyV%H9QcC2&Qpkm zn)#YH_WVkxc2pNs7)wXwCTB14<;|g;2e73Uo3=D;TTPDNcx}4gsiW7_1svDkFiXUT z#}2vN=?Jdd3LI{f@UGU?1S0>r+D)}50sso1-;tM@_z_z?H@TUG*;Mn!8}4-ASNuf# z2xol3VUA;qp^Eb{OGiR$`6yC1kukKs+yKDz$@!4aY)Z53nE%@QsydsiZ9eus=<=4yPS-c)L?H*O-{07+xMPNO9yi7gI=?>e)b|cIFX%9HQc+U$k zP)pB&>K-lW2!1Mw{21yski_FNw%yY#yJk=efESZIp=m!B2fSQ^^}cRqOWk}U1?J2h zcA2uD#J{=-ap=_-&UMA-8-UC_J#m=*p$-mHb84Yi(DjqMO2j&w7}=r!n3F8(L$&f>iJsO z@vjq0Y9^49fGS-x7aW$1+Se*}uyIC51h5)rgK;$hx8qXhc5_q zD1WAn-w)`Pwi$OwjIb%Vf`A zdH$QfBSowfQ`_q*>!^RbJ>|oSZ zAk^)%Fuh}aeLK%cb7haxzbZGzY5PM-;6(l3zjzKHzQZy7F}oESc_>LnD6$w`@vNU$ zJE&-w(CWI>{?{YUkEGMcNXi6me6Mfu!WyWV z)nY$5AfFNEY!C=W*p{DO7x?>}c~^R9fM7-|D|+l!oCP5M z-r8)DCqVVLlF6lCXq7C`s2)VP|LU^6bCkii0FXkk`u5oncww9`3{gcysD>6Ab?YNb zuj{{*9@gE$;bJj=fOLVhnegQ;yy}{%QmR42nU<1BSB%ApU{QKUBBZIdd{0qfx&FqE z>J7Dc=?!yQr2QzHk zpp1A5J|xR^pP(c*14M9rWkMwJ#K?wO?h^BerRrnGo-W*mGyI(+0KM){)mnVPTy`)1 z=N~Gv@Z=z7*JI+d0bd^82!fh<7K>{#+Bjl~Ptquj|8juyjpON^prTtC{B@PeR-5AI z8)+a&w(2~3aD^0b2mb})NVQ0e944~AQZ_Xe)z2xRn3Wk#oA0@sXIqaY?2@v4t?F5~ z+C+0Erm7FK@>I0(lTFFKVj{t)8d}C6v&8=gnZBpobIpv(s4t3>oj?a3j&^PlM|V-m zPhe=K44ue1&)j?5Wh#~C(_9*X)z0L>oFfM^>?91k$?Vn@#ixAj$7SK zZ#c~rMEBbnR@)a}JV_a{AqQZj0gw;It?D1@=KYusYrJI&#&Gy;-aj9ptk|DGOsp)8 zZt4qwfn3A+C)dC2VaLc2!c^xI0HhhGtV9z5=qHk#43;U(@;UoZ&xoYddx-|ZJZIoG zrOiHPGLE2jEiECTn4Z&>r1fMc#$f3K8A66LT`*{jgq)_BT&^W0{&$M|i7zri(wy)L@FEprvOE>RV(_RZ}rSMRGeL~+5)XMoGHUG@Sfm8)cBkQFbcNoM6#9AJ=43%w3lBxW1n7#e3S^*~5D^??LCvH_a- zX`8{8DJkbJK2)RFjLLdpzV$R1TO3tMv>72rJzM2Q@-%eWb$@*BNF<^{lA7DS`}OFg zCzwTNq+9&y5VV9cDUm*?9&J4K*XQ|TnZxPR@EYFJDA?-;N_h0};KVhq!{Kic4M77z zdyjm>1{f536ZcQ}PkiYhX>@*iDx76$P)J2Xc@ANGuo0c$ZeS0A>iENk{k1Cq`L(d2 z77zrEgTKxd`!JX2M99it*GVlJu5gSc7pVNJdGO#fJLEQ3Bt>CPtiK+L|{vT?T$YBser z!Sw44)6a3BNEpal-t2XU^Sov*|p7}Ip20bJ# zA%Kv{2romiu;|oGxIrJGW`KA&P2{z?1@*S{%}Vkz8g(}M$q~E<{>KC*uA7W})R+t_ zK8$&TlMiPuWl{%~>(;odoxEhgVEYIoNLyqm5q#fbYJ4)wzDruJa(Zpr!K;MMp5pL*ug zET)>}LQs2Wz2Q7+rqgZc8PD9?=cOhMR(OMo8t-Uxfv^$lJE6f_-SjpKQw6u%hzuh@ z0SvYi6ndew)=V_3DcEvUX2(B6b?eRZGLWmZ;bbIZ`En1s#p}*Ex+pc}t2{EJ5O?*( zlsVG^MA_j>vvUJr$yH|e{r-q@JIQ2^`M1_p{7W_6la)`us>?6@81`DvnJ1owO5X_% zbmxG0qWBq?5cT@Xr#xK$ov>eVx#Dp=PQ{mfpz8J((69fD&l=C5euq@lX9LFXK*}j^ zmlLc>h~npSGFLCU3-vTh@EUvHZ^pdVLmxQ(nYCHP{t|NhHZ3krtV0e z{iqPjc<;W54-PHw@dZ)%Q$e@5r-JU)KKdl4U<0SQ(<{F9C$BKy#sNd~&UzH@aTb+^ z>H=&%YKf=y;vCShsH#3fd1j+r7>ZT9(sKl^A(-vw0DvaUvdcyUitV?VRpL^i>Ig3E zSPtwd8(iW!*>xP}!BKHg9g1@lX)xP2ok8tU=gMz3p?P9v9AAytF+@!nifMk3Pd@#d z0dpI*qVD+$NFSWdudA(IOMDp!y69n;VmfcI`P|Cw%{)nR0w;1C!;*3;PhvWjzo#Cm z!`c&^F~Lr2VP9__B4Fe9ls9hWK8faMfdF}u%^Z3ZwRZqxRJ!ouH^|b3#^a#>=_Xmb z)Q$0WfXwwjtS?V@(yD!bJD5w$0%_I2=U+Jl=@Ym)w6&;2ZZNl`7C_7JZh0c{Jc6b` zg)TGGi^_>;P*Z2hU{mg}Xn(d_+uI^URd>jV_ZXpAwyz^YBU1J=FE*)fsM*i4HR&Ol zqQ>C3RLHRQdX)(aG9T7;md4%rOvgqNOGM@-Iu381&7!^B+-B!GBn?s~ZyD@1 zTX~k<`75Oy7oUX56tfLuX>&M52hf%?@8wjwNyH3pO(nXY^oHPthl-T(2d;|QIvh>A zKU^l|K@oXPx4A{L&pm#$!mS}x^>&CJdPG0pvJPdT++p(Uo(FF*Urg%tmsS@>p_hzO z{lsRrq-#8ozjiatE9&A=%$F_>NKzy4rk&NxmY^sREO`$NF+ahjq_O(OhYg0ypDiMNhCbgUQHJKI|tCxL4%N8tSSfIon5B0Aa+t_|AcHVfg=Y877C>=T6 z`DZ-eDt3$9mZ)n^-o+}$>s;yH@wJ#+8>G5S)YM6iH+I+Xd44BDO~JomyYvHWutTK- zJeiNm`(9vb#`D0PtqXj$V>Y!!*~uC;qQBHb_9RoUOZ2?A z`7Yh&?5dJaO8*9RhhMs?tZ{586q1Q^GP5E3oMw~B1Lq(b&QYXs_JWNd0U=8TD9xq> zJcb7Vg-TvQJKZFexMwuO?Yjf{a{to}JZ4AQP0Duroyg|rWG<2k2yYc& z36}oz`BKNAe@TFGfPH2RHipYjBsF1R(OfPkW}J*qdE+I!mk+?SBOUzAG3WR0-(k^| zW7^J3-{JU*#RSq>$f(B;4;GU-@!GN7(X;Ra%;z!`iVx_eS6ZoLYGUe$96;CMRYB|- zQX6@|CyCia=DuFu{*1LqVS@g9Cs%t&dKW`y--p?^SPLZ?9Y=hzF^=<>!E{76EVOW4 z7ShuF)Hp;%-T6ZR^U0*$k(MQfa+Vwspm!_XF@Rd`P11X$gslf2L|pXFSpxbuU;HMi z4d<&MDaW zh&I~KtKwq%(ZvttSmDYqAU%zeD5PV)r=6i%M=m&Z5YX9Tl5Gmp{zcJ zT~K<%AG0$6g41<)gS9M*JtkN4P{%^9ETx*ydOM(1!NIw?{E+d zbL*&We*4n~^{g2)c3|9L4jPdOf!spkL>ZU~CQU-i))nX*z_IiUpoT_6(V-!<#n;+J3njqg z7xewXc2=LsWs^iPXP8OwKM^m+-*O`KQUp4IxTZczuAHpIDv@&JU8@b8=OCMEK^yJN z`uKFID8%thmP91adNUHUigXt0;)t>X1`e(rg< zCWj*Opo5x;WBG)fht9C{K{%PzdhD{Gd4GAIagvzSBWAD>n8N6RIv3U;I>+`7d?|t? zQg)6Y4b$LseEG9v-DXO!Ww|I5p57xal zZsBlW!+b6YG)tX4N^UB%-A(_Df*GeGYw>UE_rU0bbR?xnNhGwLJuBZkpra~fD4N^j zeZO{q(s1{7WBJ!&4Bqs;zuSNpm1^w^H}_xip$*6l&64Y0b0%##xhwfRTr)Bs{iF>a6j{F7D@hOBpgR&Winjoq_3^dk2W zlv9*h&&2sUJkPcDA2tmYptmbJ!frhF@3O5!yN1~p|MRY#vG%?2XR+UddANJqxbb`sg|u)oN+UZ9V|pb zXX-m%wgawxQIZ)m^;gev?Bp#^D&eo~$NK09PlVKMh&zwBMtOV} zqag|>AIVxjin7db7pJ?obGnuQp7hxi$xf7nCRj|5R`Sa%$FAnY^=HUeE$9ce6p7Gr@oKVC+R<*;9 zqmMV9%w~)a`1T`|M3&+AYMpjDHVPE*gX~=*VgAPXs6rc`CY~m#tFp8lu@trStJ0Jj z&k_NSgiF1bEh9P_khAJ8_GqSrRS4)ogG^b2zK!gMbUb4U@0#y#f`|uV$bkyp73!= z^X$pGC`GqUs%E-MAmGcF|A-}LtHq1%UUWKzy1jkcF<0Uqeyv~T>r(D45qw@IhnFys z9I1iYwL&KTpNpWbkSx=%`@md@a&px(VsXk6anx~O28O!K2#{^xhyFj;fSTB2rhuR7 z*>Hvwpj?utOVYU-aS-j@G4>FU(%O1%zMm8t6P%gU!rq{08#tsvuMfQa-+^duSZJ|c zlQ?j@L7x=2*~(*1Xmk_sF&sx~G_~2h(GUzfyNRx74@uK;@c8DkUyG;VRxHU;3Uy*M z5ZsLH`M7_&6Z{%sW@g!sCV0*0+|RkhlGlsAB8xbv){GhZxb({~uxH@?g`fG&=bU9Z z;g2#0v%I5sU_9&>rPvgqW)nLz=TaSe(it0#=kTby1Nm?b0OMY<*q%Av^A23BRfDhdYh5KeM$DDjUMD&u8Ziws{_}&X*ir9Jg0c>juV8XI#zsm z5u9b{#yIfIUluhXZ0xq}=eH6}kX1%ADkz8g4BexygZ=UlHTd1q%qo?QnmR=9vqXNJRiWL`qy3|} zJntTT{d9;HFfamgRqx>XwjK7^*q^bQ13y$I?{r!qIGew~n`+UNjk!b<)m!1U!bOys z(nG_T#(8RD#_6?j{t{2=`Wq)2c(`OO;6aPt;#tZqq3^MC|7g}5aA}AMXg*w$ zTTFe14-F92S{O6*XzxkR|6r-Obd)H)zhJh|PN2Pd?J;bhvZer|s|38I{lN5&iQ5Bb zGzjomixDDl|Ve%$i0}JNaDk>{_rBFdX{jt@erlsU06$1_=-?@97fy3&^uZXzU@n8dhir z6lBXgmMWir*>C+5h6~-JQ~IHXUU^w;Vk0&c;^3W>L*4O@S?jQr(0`*!jT$O9QlN)! z%mSg7yOW;qh;eLi3{ds(>1;KKID%Sn0C|f6@@Gc^)V8dUs0=ca;D=Y&vOmENdus^E z6gr%uJY{9emEeqdMZr|Zlh2|P^Pb)WZvytl>p!;jlR_stq?pZrozb92OB(cVNOerw zg**6Ypm!|4w5{cSVT=8h9XYz_4S!o;^pJzaK70|v3Tg8vhDc>BpRZ0W79gK-HXa_M zRi~qPlz*(-A5eCa)z-F9L%*Ca@u&v}mHW^49qVM%QL@GPa# zu;+Go(unjqDKd#_z2Ley*yI68c5X(RkT@Vn{J&(7tiNk4BDh}k4T>EZ#_I|#d)!4x zSMw?J?dQ2jJqt}^~?%pGXb0uODE%)H6nfOypd2DI8(F4QXjAfE9zOK+IKX8a` z#f2*O_q}XrN!a5=1^Xp9xbs{901>T&0 zcH3DhV&p+r|G!h+2yB73bB8n$Y`Yk#CF~IDzatro{Ldz9BC>k|LxrLCVDjXSh+*xA zydDL1iO8~AS#-MskvvT*VWx?vBG8$T@VmY+V^^VV601vc6eWPZJ{_!+X~ZAs?ZvS# zJC(5vW%Dj54Dy#*^?|jbIiNxV^B5O)a@fc?^|q2T5nyOwDE)Ufa^+gaBFSoR;<{+% z`1WebpwQ^8MfKDzJK~(Jb+0U}rPnHwL2r>~fbSPH1!s8Y+{?FmMtru+f#{pA*Y7?# zekmgS0|b#GUWThrg%$?p+`@fl_hMJbi;Av45^xT5_^)TMS=fFk{E&~yX)5hO9+>V# zst_NR0>{)t3vt%VvHRfIqj0GLl;LNEpgD$H1Y$jy$ATK z-e^Mj-U8*Dfk?=ScCZI?eeqK_Ew{8b#fAvB&f%T!Tc*aO?{uj91OH26=GT8HrKP$D z1JGBk87}*WQbVpSab=mF_x;Ux_q#>IQs$FK=7P`Wdxz)fd1sdRwwyjL2}A!Q?Xla7 zN0h3B#qXn8X?}X47v{{--~IXGJ!8JRtSscy-Q!8__-EY2Z8Ils?7)Is3z2uTI|C9C za_SE|KJI^;`>Pq8{?D+&AT_Dwr4Su^sas6#kNHy+`Wu3JSyl9OIfMpDU+C%d*pxnl7d~l}n z>*3jDIp}4jjYW*b6IQ~m7ePaxIsyM!-*P#~tAJA@darkKc$Wlx**!Vmi{PPp8UTx_ zRYnju_)EEtyN_lVQct;EhNxzO%g0rnoD|%i{dp36%-TT>@#6p@T_P5ZyiT4o`%01k zV7&1CwwBr2_%s~X4nQ-OYx!y@VZ<7~pnt0K)LYIeyx{Fg9zn~b#FJlJadnWJQV3rE z-x3#ZUNp8Z;+I#$v+I^zE3)=}&5dX4GUbocv`os}ETS!=lj ziZX%Gi|z6kZv_FTr1+D)Up)#t%MqC#P6OZHx152c!U2&RSbCvX^)?r+h5F%D{hoYv zi&dV`dCgd{%%S3{>9Y^j4VI)gr?U6^-RL>6RUWGTI$%WxW*Tp*-LS(0M~zvJhK9YF z*j2t+r>{-;imtjr`j#bQ1Ttol2K-HteCGA{ww^24Gy#RQ*dfF&ids2{qo^3 z8OE2Tu8ca0W8Xf|7wbDa%~4~PAY14M(BX@9#$yXG#O7ejN5Ax&Z^OF<-Lw0c3}Z_bCyK1}LQvlOKi@qi&^{EP)DD-- zv^ZGT0Ll(kK}&71*(1$jJOe>5ArKl`kqoSU_3Sj8Ccl~aCj`Q9%#4x#2Nc|s zLW*mmYh3`!S7@@Cb9%jrjyvnlebpy5G5wsHy2GtRFh{!8NZI^Qpv_9Pe>uB{WEI;! zqXs)!I&4uk_4}uPd>V=VwBt?k@bzEj6agKW?9?Ut&W1=e}Tj5s+6eE3_T6gcm&j#M*&I)AU z)A4y(bPcBVw{nhBd|^A``tJf0+o&$_3P*(;3<=_m7n;9NC!1ADsI`fx)oui3EZevL zfia?u=byhqr4H>X=tIP|7!rB9i^e;Jd`agUmZPKfwJAiw(qci12`Bo2nZ@;Z=HN^- z*sY(oYns_u2ublPUjNl)8FKAvo^~K*gw5FZ#ddS0ek9?T9h7@giLCirQ6(O7GY|c? zh;=y#>@DDC0kgHGZ*XGRdNM~#P*%0ug~2QWOMKx0xH+ZxCF}?J@==aqJNi-JfOrVK z*Z)T2_!;0KCp`3C9{sn1Are7<*k2TBmipZUnXlv3+AwIg5o0|`Ajs~*JZjlKjk7fj z)D0#28?$RUBm%8bfw_+q&nJCt(Lk8UHe`QXY)M!I<+sd1yVO-o@~Qd6>K{)zz#@{5 zC+HC^pXGo@i91K8Nn-jULVqz9>8!8#pHn&sI15ZFTf6dqSf*oUmO)YANW%UZ6`At z{3r5{K2QAaz*4=s)3_&P4xkVV3L2WLawGcD!gI-iKIIleyOy;ofd0XiJ2E|=Vm_|C zkfhUXoUM#Bp#en@WD0$5Ic&l-LPfN(d70y+?~yw zGyKkwb!L`Pb71q`F6X^7{LKFQ0CN0I7Y!J8p zk9VKuT|1Y~9P(vr_+?$3L^?%YiX^`j`Tq02FZ1m)dSwg=NFR?%oabj&k-M8Je2*A{ z%1@-!h!@&{qm4LMSX%hS&_!N~aqP#YycTi9Qf`nQi+BU(0?2W{ksi>Wr>oEG@D1T~ESRV-|hf%JmyAy8CBV z?PexR55bfxg|J0?>L9}pvKe^5rftfP=cOSC`mF|4V$+7p-?Hdk>g0dtaIMh49k@&i zO;dB_)k7^?srx zXjvnmT@&BRUN&N<&_`6Y5`J4D!36ZaR% z(tOmfpVn*cclr?ka3BEJMe)ndJ?{DpQ~lHuVwER78x7{AHbM1uFN|?3v-?_}p}K

    &`9wuqWM+4#8kbE`b!XC}zW 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

    ;DoNp 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

    M3%O4r8 zz1gnlmsg6?j@qB%Z=4~`#!yj1rlOTdSLteymyn-PmKe^^n|Sx9R*55zyf_o_-_$l} zldSyD;-ux>(Z%FvY4u_%Xj<9(*482XkpBO^fhN#C&rrVk`hMiBl^KL)mvfT^y?QE> zI$fpPj~(bpv0EYtVmJ$mn4J2KV4)hFGsh)q4K&IKrH_CH?c+}F*}#zMGuA?#g{ISJ zsE^B^)SJ}c*;EX%pc)-vi{a3n!FNdF4zOT(4H>o-&&>#9(aV*Y?8lyfkY15nl<(R( zrJqpBQZ{K=1$}LJ`pot734vy&>2FKfU6@g4dCm*8U(F1u@Dm`)_g)&T=P#XYIF^=re8yDd6+rPQvJvc5Vv1Dz0(e=v8RDUn zo_w?9pSS>m7bnm?hSf9h{!)drmi<(2kT3ZhFPRK?NP37QtSO#_EFo4uQw}GY z-ImD-wS)^r{l{6ud1OVtbux* z5QDCZdIlSH;X7iNpy7}42|$i9kxQ8|k!)+|cZ;nX)bSUA4~$WTuan&n0P3fLG# z!hXAa;kPZ<5S_7X(I8*E(d4fpu^NrVik2Hq%tc#r`2yu>wzdO?1X@l}A%6%0M!i>Y zAUAWFqkFg!1h!+@Qh81l$Dwsf;TWQxIqueUHflWS#Ki#P;xfw?RzxJoG=n}1WTJs! zkCyybRhqyf(%WORI97fD<{n3#g5YQ^deL-GuvDEWS@*0=s{oxiEV1a@8*5}FZ8oCX zni{Y{Wt1wDoV%mhiz)6+(dX-j6+QjWJtr&8l#lkFPH(QRfNzU9SVw(thI60u!&?n< zmt6t`4yHQ*zihBt(L+0Ai}DnB9Z=c`(|N}ojY_vAHn$b;Q^qt`^23cp3X4r4IFyB) zJ#~%-J1&>!^(@AJm$Fiiq>?=S-DEsZBWKr;mNty91+g(^hX!Q_L@9@~Ep=*0+6DxM z4-!t}AJO%x$4UP&do=0Evxa4)bk<)Q`0g>2GJWLqUbK|&@lj~dpyWk}To(uK##p9s z1)LtMPy@gJ)8TkNdp=|uFd}~0={D%`qqcO7w7(0riW+F^-A_i~{B`oFD$eNjeLh3g zD8DoP_^Dd2p`AGBkvr>dD?adhp8st?RfC=$>uXh#YbUGwiDRCt^Sk4Pm{>}Xb0EkR z8jKi<@%l3jon9=FjJve38ri-L>W+T-`{K1SarW{UWY}lSy>q;=in9KKz8FNuBZNAO zZObVSR4P2vunjcK>WPLRLe`MxN4oAsFHp|%Zkva31)yIba!0nD(I|*5t{i;nQDYouOP+NShc7=|^ zaj~V~HDHB!xw_uXqo8z8&z;U&)VtjxE-HzGt-kj66b(=pv(7NzE7tky-SeAju5B!c z@t@FQwy2U=+JT#(=NDZqeJj13-pQ?O@vQHph@z*wdXC}tYKF&FE(F{)A!*oqs@s2N z0HvVGLEe>M;y*T*9hZigRag9E5z{A8f(#tCzzb5mB=i?AOiq=pngid-01RBGu)iME_2r1Ll zN~D3ViSuqi-v_Stn-0dP_x*LF5$!BAtJSEfO23{8D2=I30!DJBUVUlSz-3F@n&dw%dgHoUiKxTfBbXa zpVOiFqLiC;(Rk;K*J`EifBkdizYiUq{~0<*Kd;ZmZJw;x#^LGT=(0cU9~;gGi9TC+ z`PnNZBh=o#$~?aFYTREm)v|WYGagSwczR=9ZpW`{Z0@JBFR_{VkhZDI zR|p@23zUGYcDP_&T#W-5V(y9l zLNzcx=sfwt1Ct-I!qhgbf7H@BmF#`u`-5QzpfTyIp+>4#`UM&k+I@FOJ6ddIWYitu zRUaC^5wMV`(Dis@bH4H1SH0z6(*AAk2gRl65twanisZK3Rw_n0m<35Wq<3k4ez<(q|To<*{;6+ z25TffG4wzJVf>c$uMuRz^1f!}zE%dirt}+}_@=}WGLGsGt~>KY5-*QVt1Yf5S66~{ z3T5xpJ~;^JzI&>x1{n`k_w+W-m?lPKOHsf^!l>R_n7yGe+!E1d_=JQezb!}}EAavS za4{i$^Q<5o?LxM5fvD{7B<(rk+{+4ko%&J>k2;WSC3P7J`X%QnZ>kIoq|eGwwjxzc zDeW2-26_sRGPux-cZSC8j0Y#!zNJX>!L{4IcMYKCNOJPChCj-X~VUhfR>IGt%PeRN- zsa$}S+XJc2+mYwbmp8O0KeSX}ox{zs1-fCmLDv?`(Y7(o&eK%B1Roacs((+nO-ttX zQN=IpA}2o;HmSlm?i->0MgHSD4=Bsc^IW6uXbQ9bG&~I)XVJ4IV>?NZSHq_uwnRnr zipK-$C+9}jt9zV1@32V#O2Y%`?ilg!qlPH7!Ct)X+fLjIXb_AF2WGp*CqOfb)1_Y^ z(RMTL@Opu`a6Zb;Xw+qzPne?I{0KV#tss%^ zbS}>I4R9z0uF5iaAp;g}Xuc;8~FNgC22 zFXtn@jNcw57|HnQwoI*?o>$~pIk(k@o*H@~CI`2k%Di#6WckRX2&(~&lX-hF0)C6I zf{ypyM0OA>T(d+vD;5<_Jrg9V{;qx%;)d14;-sb}$~xA4ymL!}nIJ4uCHtp7 zy<>ZOciXF^p=8cirYZfecn})zT1rQ`4ifhcmmD*ejXnj!?q)kGmAbWPTpK^Pk+0=Y6uGfElEwX zp8%IS!wNeN^VuF(-vhU6c`X$A9};z}q|f3}Y@h3p57?YPI& z4t~+=c?gwG!GhPg$b~afNNt8lng_f_MOeT(q+`=Apd4idvmlR5X)V_ADoMU#0^sth zXPT4uXovv1^{{GBzM>3Nm6Ga=2 zg&WK7S{q`yyBfk?p7V@)H(vbMTWV6@bCJ-J1MPkWlS@ar&H4@Y^^c3>4Z?gh70jL4 zs=6;!aL3J4zlMN5o*<&G!*(^Z zT)=a!h-)L$Ai|>P?K(5dsZ;AIN6x9=FLCsx;Y8Mh%Wgd1NkW?bXlq8fr_;t zO|4(eaFNB}kP55%6vHJ7z6>Jhbmar$X{TW?`3AYEPjPVQ08qIYKWc!3%Xm$;JiTw# z|A+l2u)$ouLE$~|&$zu|;ooEUSo4Hal>4qzM0hw08QO8QZn=Rww<1^t5~2D>EY`9# zBjSVWY7CjH&>O>IU!w_qV4DE(kM9Z}lFvRTm!;ndCJVX^yp>T-%!zSqKAkl|)xUfn zXP&RhP2bq#@)>iD-x|2hPcSkr$b}sgi6}uqQWaR&>4OMJ9YG^0E0Jbwr~d1(cy;k! zNFXx~alap&SE*JY`!p%+*B}gZSwuhgW)2x5*C!--Yt#j#m|6Eqw7)l#?9V#;dOo?L zao&q|TiaP1qTU%Y@Z;m-!pk|EvGvY_g3{OwDG1;uBGMKrpOiFS=oYb2N9t&pafT^Y5)0 zm&`i{iBBmVr(gH<(Pj%jg~FOQ?sLRab?vgvNLO}?Lex>8?(rNN&N`c{vni!t@Vu{b z@K2@Lb~a64!L6Y`_Q<*}DvA6rqOrVBGl)3GtuD^j5WWVPx?cRjGl46Ur*XqvE`o@* z4&`yq0@HgZ)#r)6Z)b<6&Sa+TGp_qehA|GxNQ>g~M2v?Phnrkv^b91UIgdQ=@1(6z zjC!Ji-_wg?@l?dny8G{!O|{&296y|t#0XQEB7Gyezi90i`7R!gBvwx)|0B%CO46H6 zDqNIBkH+1thZFa$g{HBm*8VsYJ1py>1GP@AT{4fhLP0>cgvO2{=4wE$RUZG=k$#97 zz)CtbuyZ9EDcx{z?{sSO*|er=^}*cf5k@a=Y!6We*_Kx*{3|3CXO$Y_@lJJkA2R7q z{kQe9NE~0sU7#CFkW^eMexT;}MN>N2AmY|Rry?Y^Zu|CgUC=G>- zNaM^}RvNeQoBjFxw3lT)Xj6=gDO@xs&~khglk(5v@r>1i>E8R50YvEbj{+V&s*bW! z`=I$>uXN#t^#3z=tTTIV#_tLqTDN4GB?VN3?h%`1$qd43v005qKXeZ!N&D>IZ`z%NK(rP#zDB= za0J^E#HTg{T~Kx}H>!I>6F8zO_8>z`0lwS(oG8QeO%+Ld69P0ct5HtP<(~FyM!XKY zUPe0=lt5-+uL)I_&1b~^_ghxzT4)Pw0@N`Fs|;_(Ihi^uz&&&ddF8_eaO)ad8E8_3 zZnD^C9x^4G72FTKkS%-j@xqEI_HA=XF$hpKcox403l8AdG$5goZ`)l_TvB}-^jcuE z_ckr=uet2zPT=4}a!Yfjc4f-Lt@^ws& zzhsKs^n*irrRfEb=*<-|9_V=}Zr%)BPszr;MMaP0Xljl>e}R*1419gLR$Fa-Kz|TN z4H;L7+xBX32fuXz-yDtI!56x|IS1?zcRgjX>wV@*e2Klbxfi?!r&j=e@>quE^dqo0 z(WBOh)a2Y~=JWuBRM}4BSg{5EMBeY!m{1LFWs(NFq}x5e2QnzRX5lpte5io%v4p)g z?iiiOWclX)gnTM7q|k}NNt%55xy!J#D5AC2p5twl@9H&^I$L~44-n;J3L7+SwKU*>xVc0a^5r& zfN|&w{!kp_o-atR$+Zi<`^}qAfmJ?8#3Iao&4qf?PW>0~z9?4K z`McSMx#9p_8b3}&>R7TzLK#S5>I>ED(%X55`nk`uqH=HQACX=4FrCgf@zQJf?ndhO#E{3GTl~_&m)FP1MIDQe$|fs3)OMVG?8cEV;0ReWGa* zM7cR#hVV8u#7bV4*%KT0%WcS769R<7znrCOD;@VKSFg~ol>&+oaFPQYUJ=1>c}gVR5d ztv2+F_!nWjvzV@mR~QvBGh~8^S{?rPZd~EN18s>F|3A-ZgLf&JEBpN6{OS>5Id{%p zcf;#4MD%FuO3y8q`YOwPk^EM$e&_1(-}E^r{+MOlV-S1{F?lb1W zi7!Z*K{GN2kCcL^$Xzk-;WEdJ;Yo3mW2vJ@w51z#iogF87mcofw+@&y9CI(m^Etm2 z&CwClaqBI%Ee}r#b4^WlxV@EoAbxO8>2x;@?AwA4^4hMw?!jP zKMtCDBy#G^jXDJkMX_%*bvO>?Rm-7C6lP5LtLIN9f+h&q`+DE%o+6i_(-)HIZDX;i zctks42Uu)J>kwoPj0d&I33=Id-T#vL!UjyxPq`P&1Zv{b47xXiZ=!oHJI3S9_(V~S zQYgA(mJQKtF+#xejPG)di-HGs!qM(teI0_&rP9x=x$9Ol5EP*8pF~O;d;f2$Q$6qr z(Z@dNN6f&pTa(^Vd+Z;r!@UJ!l+lUUDDU1s@u?PwkLNF8^F)EjtSI|wcf4f>d!y)Z z$4z^%03vsiVV%eq@Jx@@4Bl*epms)B?!EW%w6DlP=8r}99p4@$JO8Zi{!l4JX$2bkKQ^J(pqpAm);X_d1{bn0X$@=nE*y z81S&-Ww#TmyqN@lE`v&;5Z;0(6tktM3u8H&HtCM08 zE8Xzq+l&1p>Y}BCqW8&E9^`t)9Ggp7B(7I5#>Z)D;{kV*VNsFUwV@Bu<<#N=WeeEw z-89U54@IGmpE&tAFGx#aZ%*>oa%F$OGFnkg=tl-I1G?UI85<_I%`>gw>e`tUb>5A9 zM$E)+S9;p<<-dfuJzg5mu9k?xQ0P*N1ob*GE2fO=>gYaNWx>hBl1g^TLmSW>d==Br zH&>re=2HXYVK}~Z-6W$8r=P&l!iRw+$`{G+X{p6*ZR3pn!ik-O`1%dcaBA9D22EZb z0mstCviwdQoUtw^ZlvA!H)LGgL|T~bEq>e~dwaCHw$(>m-xs|pwjnR>C+lF36=>nOSSO#+CnISNKA0Vh%?$(ebPy%iNdlgBgm@7+ zQ9p`4J2JQncNrTXs69eq%;x5UCc6{zgvzQbd>SmPI=F_ zaD`{bFb0LYy~%UOE87`)G%B2dJpbwi{H#0iyx!P>avFB`M+DwO=v~o(4LoZg-4aGn zN{}pOtR^mQ6)g!R9jAIQoX&pI9Bn|>wN`ibJ1&%*XIUG{2+~;onIk%6(q@-6^m)-v zx->xCPkl)Jn{{3HPYY5H^Ue?dbr17Qtn@z!!Q^9sS>~HBF4>BFH}p_KH*2pDlW*pC zkaxG%gYkcKq>1x*4r4YdR+7-B0L z59b5HjNhB#8PEhJS>Ez%CW}POYZMMA{XUcX;E52~!>eg&go}zH8PSI**+vy3M7Scp z;+At_<)XmE{!|kXjP{GyrE-G=td-|j(Y)K5uxvd#>-EvprYL*-M=whw=2Dl;LfI4T zeTCc=AE36_h%jQ%e>_(uLiH@tkW!-wb(nD8Zv6f37%8yLlkiH;sNEOE zk zfZWyV^c%&O2t_Pqf*}DbFqD-=ao5bMAfAXsr##(KPb+zFZO8NAH6%bKk_1H~a`@m* zT7Yq1?}YvTY)S>Dp6Hbb{@z7d{DW8VHiGvjgK-ECwjLSdJzhF;3UR46uu_yDmKW8} zwNqdy>94t$danPifZFS~s}z>6wT%?7zGl*>rFy8UT8!wlCMLwAQ)5G@+y-SIzYnr& zoz47qG-Bnw>GzD-JSeWvkLz5Jr799G#-ByZLwfW$?l8essEilRzh4K(=x>U4fh(!F zwcg@T-^jw4Gk(Q<-s`-Od(CG(v1J1`{8(L#iG5754}@?)n+8h#25!x(GnbZVS-w*) zV0W#tFNCV8`IZu)a)p=WgLC29m!d!quy1Fae35zpPs*qWx^Xl0R_ATA?PKB<7RBax zp^TE=?+G)rf-vRAsDvoMLvXLn+7}YafAuRzt!Fst=@Z(gVPz8#@jHFR*Xk~xuCBeF zepS8<21z=48aJj4r-sE!PXWuD42lVED0(W+>AOjNAoA)!zA!nq=Fhj(O`L7ltKg{q z8oYe@#sl!aqeM0y)o9-)e--nU&+Dw8m&4j}cV@#^+xEwhrX~T-?Gl-LQNH@Zhd?F! z_L?j-@2RqSO%v~5>aR*QlC11}sbSfE)n^XJZ(2WDS)a_UT#NmcGqpyyl|iJT(L#<* zDdQH%ILuNl=?$ux_4NGsX(6+5mzb2)@2+dZ@45q; zeH19k$5-#m1IjPB^6(3L=)842^GVyW+V4ghrKs1O9WTZxe2no40EhH(Nj+CYuldQn z($r43y{i?ZBNC#cTl{@cHXhbJA1}X}yt8VIdW}f5%q+n!Px@3Aq|vPkm2UnS1RH-5 z%J`Xoh1P8$_X9S2~1b?9JOm<*Vm_p(Kar9FRn0tbTNl?-2@#&a=5>uKZzsiq$K za+QEM(POP_L6Ajaj1SKN1@j;^(wE6CS)AK5Lp+mmM~8D?e%>Pjp0e_3 zdMp;AgH(j|!L?cL3Tn`leqEWkSqqpkgM!=Bq^GFjD61}Y%-^J5D6xKMBr&uz(rIs% z=XB}Wnh{NM453DwB?GZjEMG4(sej?;JSmOsE{$U(N_`GgkTx0SQQ|dv=SD2HT-3Qj zjOj3m8!0~20`2>DVgh5$<%08hxn8M3>{zckutHSs69Kt?Qsyr&w}&P{j}~3eiH%mp)=r#0*WlYg7%N03 zyYGkE1O8_AE+Dv0IWQsMhs~bROkuaww$ZJ~*<|?%M8?fV2=$MPPh~mvPdmnGsD0rd z?KL4k9>XRZcsh$@R>_fSp30W>a!xQ*2#4gsy2>59^m_VSa~V4$iWzy9wl}WoMWOORiL{WLgTbKXohuA;yUo_M zG<1&^y!j?QdM@NbD_I|vC+?h^YXTd!@hzJd1LBLz|JwssNkhx?@p+BBv6<)^`-s0^B?X(hgmjH zAQNfcO_Kw(YiMA4*KDrPv^`=W56!Q|KaF7lQqmUR_8ZH=6G&K#2@go`d1O%aS_Zt2 zO)+qG6Oa`C6ry}&;K$N_GnL+>!X$@w5kU+_um4kyQb~CcXsBodm<%~X8*&_~RVf~r zC6J>wh_OpewuFD9{KS;;haMT(eAD*SCpdA}4U3;tM&A+2rR#S^|O;umnw8<2lkA5u|jza-;WC=nkq;==b8$!aYdqVlbiSdvV z2d?Lra;L$gu*&B~^0hNUYWjk7^gi@QraWT=uU*de=@z1t{~6BnF&g#eRv+U0yvaL> zN>d4pn%)toS$K6**qWw`sOe8^81Mui#@J<-gW`WxB zb+p%~t)EU?=Bxr$<2EQ%44Vy=C5=9DlSTOC&V99iZ0+p?%x{$(5yg>UZxZyUWyg`N z>7-aSQwZWbSDR%B4oetddCQUsHYk6z+@?qXmKIq>I4c+kHs)rOo#i1B=#Sx74umJ5 za%yxSLmFakdO+mKI{NJUd?hys!pz%tVf-Oh2{mbE*mb?Lv=41)7K^2fhV?AgrJAoa zzi}9cP`D1q9)-~qnkvWPrcqwTGjaJkYOYo5=alYQ{M~Kn%r}EN;K3AEsrbKDbM=2l zvNhMKg!3h9KtPDHAK#I+ds9yg(vLidTx)7{TM=*phx5Vm3A!KkRJylfnF5N)E|86E7AAb(%b%I(r%P#N|*W9=Kq9TJ1f zSWo485b|!q4!qjDCCD-=*@;yAtH7hgXW^bqjdXwf6Uw7wwn&}&JD8tYdfo!8BOPPV zd=Z^7QpBLiV}U91(UFEuR~x{qXt(M-SeGTP<#;;-V}^Ho&g+A>LH9!QUv+smjWm{;mTUd|mT?QNFwIaF9Sx@D zz&;&3`+=^t0^~xvDBA-@qpMzvO^vV8_!@1m9^p^q;(#MqQarg8);IRcvy)FtHn@uc z2>vjt4eG@<%}w_GWjNA-`3fKOwIB3U$K{$;quuP%IN1;5Twto=+NYeg?T2wN9@G*y zpH3V5%h%`C(__gei{)B;!M^`hsjoMutW-2Xy;Af^}O68=G6xc%9A{m9)MrPX; zgf`&Vj=G|YwA7< zctE52gLR8CZhlj_59<%*eq`gaDYp3+Z67#_{KIumx`golSb2St)%8l{Wfbm?(?QbC zuMS5dw()ki_O$qFJGAj6Nq#mLbz?{%2knaFgq)4}4`~N!T`naDlt@}{8eJ{(NXtnE za4og6-yHL+%-b~lE`UBAlv^0D?$i&>MbAlG^w0FCwHf;6sVhiYsY8tGeUV06^zw}1 z5JWH4fYYqsnI;fo_|-(m|M7Wt8ViARbOdU7o}x`do@nbs1j@RnG;-&3Rx+ryen)fV zl2edKru(cvO$g1ANR*_KS!S^>Fg+aI?RC|qXGaHBK3i@a*24>Jg4A`mWTY}+tRD1; zz80pp=!<^97%`lh#Aa|9L#UI8sXRR7j@cA{G*i?BS(ykcKyiz0Mspbp0eff9Yoz~M z6S5w!xz(My=@unYH{QXJKejzDlu#@m^0XPWG!J#$M8HJ?qhArD)4D_)E+Q>kRw0EA z!>Hd8M`#n7PKedaG$7z2I(hgK8}J?)nr2`BrcB@*<=$rw7*s-yc%yglF5&a1Hih2p z%vzrc;GKf02@*0Z!*yLEUr)_ZEL9uY(B0mtxg_)9>VP}SDocEr=Bw?@9QTl-dHtebeC-AWS= z%K(5Cf*aDJX2EAj#F4ZlU=kUuTQ5^P7bQ=?`=H2^%bI;dNYyL{EFE1e7Os`yN5rd~ z-}TAYuLbi37gA1F`6)D+1h=4r%Cs9@L=j!kSLFxai0G>uf-~IwoN08Cb}e2?k!mnF zYl_%S-@tUBzti0{DWLJP|3dHq{--}3w&akg69ubW#y`e=F40gZ2<0hmrCZyuB8-Rz zaQG`)<$fZi`aaoU5~Xq_DiCI@Y_sGI$VJeQpsma$10L?6&Jft_mrYhO@|)*Vuv(qA zE-{DrVC6*073ZpcR9aR(+6y*P=fg?Yw#1t}%LvG1u0qBT7XKM*{?|q|s0K3FQM%tF z;DCl`f~s=wgSZ>v;mR9m{oXfY_u_-T!2jdyEZd@N!!67V%^*_J-5}i!0)j|~bhk8& zbPWn3jf8YbOQ)1DbTbGzbi)kYotwS)KX|Y2&$s6|?kmecE8JGm#k*%gkv_i3qi+keH3m*|5&^#}gc ztP-5C=WRsi@9(U<#Ajud+NaGr_KK;W!WLKJVYIVSv#SlQRzB4sl*Cm)Rs1>S(?*TB zVd)Q)Av?#vvTFEhyPx|Ooc7`M5#^sFFt*IJw5sg=slWAVBWsz*(O>z4Vl1@ z6BBt8xA)rPK5-gd`qMDghfRJXdC*AmqW0(l8$U0*+3QWNRb>ke;P=)#OMt7kgml|* zV1LGWAF{o_NeIzI1D+YmsZ=65bPK<7`vVoPb(y*E1GpbSyBX|VK>S2$B`B|__-yEb z@yYLagaqFMbvM8z5yR6`p*h%W&h}GH3!}^|)w%BUZco?J!ASGqZ@-_>eZK9X_bIQN zyDSVF?JlV15#hp%a-gV9Ym2n?RvHK=M6;XB=DJs4UI zEANz+b7;9e7l=j0$qOgs70Lpq8FUD!kEs^qBL?ffStQE}P|pL$?8J`1;R1(u%Tkvs z9v7@NAya2sz|ogZi1uV3-l{Sc!$T7~FE)>a*J4hU6IZ9U#&=&UvcEKi|B6}xjdDt- zI!-Neg4N!*3>SHT)uZ-r1rOXW$?uBP{MA5R5_z=ns3tRkrPaT+2RgeK?iOnSlX|-W zAM#3Hg%+RQe6Q>Tep-6?_TrZNU;M$GGQ!-|;8-tyBkRDhW{x_Nvc;?h+CjQ~2OK3z z%jnHVIf>huVLea!4&B8dDg4pxffSa`{XO;uT4g$3ByPALJ`5SKI|1TnS<1{g7gWB) zD&=We4a`7L2s~T4Gc9W4t)7|d9#}}=fy6_Y~`xWk|xN7=4zh)SC zC-mZi&S?K5&V8(Dwg#Zuqs~C-(u4t=Xv}zdRp0|rG3IS4H>>d?MuytImnoNQjhnij zxE4|B&@MLH7R2Yt>i;QyzooVTd^elA^Q0mRdu-gg^=H}Syx6jjE6bTg{5;HQ|HU6s zhP;hR{ckm6o-cVlI`;ijy?=yvY>EVwi%F3O7_oK@ml zppeJ+_w^^dNZ}`!&KwwXxSpg>9E|Md=K}1ZtaW&lMccSc}$}SXrAp%Dy~3H3>2VLnA&eX z9`|jg1T`F3{2V9$^5k)Wc6B5E%EOn+I%Bh@qvfkrev~T`D%;g@aUpWt=w>!hUY)8n z%qqI;h#JpcvvN}Nc^sS3k-z6!usc{<&?L%gS>2(?6*)s|L^~9orIKRZ7DSU}FgX0q z;c0ktj3c&)4vVFh>H7&@YpPLCP|GIcTL^pLsV_;tEN~R{Izv#)3v~48=Pt z^bxG!cXw(78VjHp4s6ahZzXV}#d9;YQHF{94xd4^!V~15v-nh+Jo0|D3ZKEF10A89 zxb6I`Qd>`G{;6o6qjj7qM6bU>j1os%1-ulvAQ}GH_`kDS#sZ39|FT(auO!xJ#I+MC zK|J*>c};Gmx#@SLAB>6Y$B{jwH`J?J${`ebnbI$O(Hg zJDGt`D4^+sxkzndnw14=KOEC3Z9=SWeI-!3?vZldMft&h7-c`+&UbG~}#;Esy!VDTuMpm9|1Ml`EuHlr=d>CB^1gGX0aK3`p-UQqs(%*9) z<7L}@k&K{YhzZ@MuwD9)Ln2oFj zxCPR>b&%IovBBBm*il5_4MuU_%fW--nEs~ji|VNrJCeYn2ntSpHjgLTrtOzm3%l>T zrPloC;=Lz+ITZ3q=oA;LxM%~hlIH(5-f{VMb_$2@UESMs%Hw!iz7< z`gg2B@l$w#BwGiMIM+JkSRXSoTBVd@LOzal@ z8z%Bu@XSOkrj28S*|hk9W8SE-WAV==bpO}*wYAeB^9>^b0a<%W9~PAK?{^9Aj^-Ds z3(I(F`Mgt~1_Qw#j8pp_?Ko>QN0e^bsg3)Id2QH^8{`96l048iSx`*ojuP(l%q(*P z2ujb69Bguvf(IHtK7GrL@b0WXuH!YB-V+pli(!FW9}8c*&q{}Pf0D6TK`$=OULy2y zO?XP6w~nDE(k)swie(mcdzYIqo5dmRQstLwpY9{GzP$4LEVGakHhLn?Vy z!LM{r0Shk&mU?;V@QCA09`PNzpN+o1VeafH1t0O;9{Qg6(1zRdb>v{9+^Hl79}+p9 zR2#?S{2r6-{_)a3y7iP3V$!dK;JV<)7YulaL_ATjOons?nEl6kYTE3wH#2*Z-o1}6 z_Ci$qn-MkQPPME?7RAp?KcR_ofuBYk@YtGt8^G4wGMNv8_5e0aX#?QFD*G)zc$##4 ztwoB16E$FwX}o71?UOqkQ(YZ$$w;?tY=NbH{GFMWd{*UW?)La+BC1&xs9inw#DT%} zX9zJNrtSnD9f@e3(fn^&meKYG)PUY-7{3W2&#L2yW=$Ve-DL_A&6^->gaj7|l72lS z`upb>39Mu;Lnuw1yNCb+f1AqiTNni9_?iU&uQ zpOG{S%4&(3;}%ZtFz*=+rdDFjWF0>qvIw+UXu>2bX2;SRB;XK)cMOkEYZ6Wq+!0xsa`I2SLL#3Mk-2Omk^;n(8%`LPg{m@k z4{yTiqDCKIX{FWwbLP?n@xCYIoZM<@FRNE(l&3b@gbC{83{;e|E|dFGBkKjjHscNW za*_c^GT%6og@{=Ryc70^`{mGZ)STm29^^|p!Nr|V_900g!!TysH=_N^c;1QKKD{JX znW0~>gZl$NAv@&SGLZm@_@hod)VxHgSF=gIhmLPi^l{#9IDep`F&(Zb>afB4YhluR zbguyYOie{Yv%b1YR>I14?oXt;^X@$+hWC%?U5DR_+g^8rYCu%=jVRvYf~z*EENSVU zoi}470Nz2}%$8-Gev^&xHJazf?- z7k$2H#?^9Sha$mPp(L%=mkncl7a>k4Jz-G2(SPu|*|YK+23Y-1)!z!xsP@K50XEGN z`}*$?`>#BQyfkMLSRxeP(iBQwg`4?~26{$ShdkI;w6}jwF-A`oX4Z7R|5}SG^mf>j zOvk{o-lFJydo5$uMD3uLsEC zW?GlW`>~n|?P%+Q2zB_r9!BB27o7-jiJc1ub9JpeZqax*eZ_@IKGZ?|EiJwB>FWUc zl-L<=-Z9p+-n(fvER}Ff2V&NWv8Wctfq|&e@ASmT8+Zwh%(WrlY2`_*f4~i#z!y|5 z)<5#Q->X>OjCZzH9M{@ewR(knoT>gqjq1${#$=5XKsi9 zpuA~5G_(a>Ewj^#1PPd#7yE#SNokg>>G$`(!KnH3aih(s4q0>=iJtq9;;VebMv(rO zP_ZWw&5;_FvJ2aJ*8mB=nh#|q^|%wSJ&?a=yBt8yZT@rc5#rHQwHSL=6A2hk1`Nr8 zMNGm(*QkKi-E*#6)8Kdybi>niKQb1z?5PfB zS0xYtgAgu}ov{}qjrA$N3^pZs4bwP~g4ag>>G|ZSp7~NlGmtBx3nP$0;%N@GrDJ~2 z=ew%9nUwdRBVNkiZw^%WF=D1!X9dG+@kMJ#4qOh+pGo~B?{F~fiMG>GUL1Mkt~@0p zSvv@uNNH09KJFt3Tk6}d{rvS(1#-O4G+>w*u6uBPaPmLwhi%pny!%NPivrGGMK$9h z$P^UbKLKn_259C~r;N02t0&$(hS`$x(@mWTy;51JeI)$k@zFdd+GyVkhw(1ad?1I* z2O-)?R)i1{D2Yd(c6l7T`q`DsPoI5rdb@9`eO=djZBqytl}zow{BOs$(_0@^nn1+X zMf9(d2hDp1PlL;uHUFDsKRUI`fn{_5duA?Khr^8|nd1)p(PG$`niN6&)RqZ6lOG?MWU+Sy+-rUk3;(dW70yew0Z6MPZp~zcBmi=Y9*Sh6 ziFbKL(kUf!>t)mbqL6uWRd7iR^a6MaU!ofC8O*|0iNV`Rq0liZgU>-9F@NHGe%sbS z>qov|v!C*LjyP6w7oF^!5jFi|qrAx<4vff;sbo{ifPe^eREEe?ASC^#QDDr|Vdq_h z@3A}d&+CG5^r8BAZ`zIXRn+89w4FCTPu!2Nr++I-ZvLpLqAh2Fdu0|VxZ>tAW9>wjQzeikC%FK&M=Q?oG=ool*Xm2E!*Ul50{2kOtVVuNSaS zWlM9aS|L!ocWO;Go0d31`YsD)&1TH92J$MZvW*cGoMghxo2K};&%+`YJMry%fsK;d z3Q}vz8p}G!Y#83X^}1MtlSWrcQ>L@G+KPGB2d~TOChKoY66b%c=UY{buOx)^X!u|q zcYHOl2TomQ6V*0uQjhG+hP#vxAQv3%K@+=K=k)JFSXt^2yWhePJs9x5cU)$vUQ7|r z65!Y7c-9K}jD|+WF(hP6o)(qE!xP^A&2Yxeq+4sI8(Siq{PqEx#TxMMZJ^{pFwnY9 zpp2eXz6w0-HOjmB)qC5fQZMsL-Q%eqHdkHj0zCXuC)B;!%#Kk&Z%yCz_($SX6V9oe z18#JhTBj`kkFa57&{bBh`O!_p#tzP$a++PdY1>6j~0^loSx=d$x!dC=?fh9y6VPY6s+`|P1v7^iA zRdI!0uhmIpe{!mFUDV=OyHtJ!!Q_epBOjQrcgOHk;Vvf3`-NI~n$@}q(JC?3WUbJC zbjoC_PFX8MkZ&YjQdrst#jn8zR#qGnABl+!lp*o^N2`VLv?0?2M-L99M=J-GPuFCB z`!R&!uIvAd7p~!Z`X`OmRcm9J`*L~jx`3aPFd{3bhT91@NHfGfkT-8QM0?wfQN#%L z3)p(jUmA^%hd(kxstz?Rym@(BFC1fN9&CE;HONu9Zub;*C>JjLhc`_CW6E&>J9Yj3 zJ^d4!r_B-zss?14j#el?BkaXc4_||=(ct7bY;^^qw3t2GBt{~;v+c%9oA&TdtE5Zo zfKamcIh@2LY{`VgEqIlu4*OxHzhCK<2;^4%mYC@`9cFN!BHCJg_tr;f5FoDk+ej#t(F=eZ>nn9G?WU2bJv+M!`94z%+`<6(* zSb>Sg^cR>#{PuFQR1DVd9<`Bl^%!A0vQ}0Lbr8(CqiZV zobj6TY&uV&q0Qs;Sov3+<3{3cXIYy>s7obQ%wqT>a>jCObsXF-!MFSu$|ztReN?{=KMiTn=D9I+ zj5-qeRwA>+rA<1w?JlixQ-1Z~cZ(UqJam*?Hq&h1Yn-r`(}BlbRuEHIg{p=-J3dQB zki=f^WNTS|6}DVd{g+jLPJk)Rw*H)=S zpzubw@bShh39NQL5v?A`pv~u^`q|Peeeco15p_VUz7-evgrfr0ffr7P7aDA*zE8C>2<_@z3IR&&& z^rKn5Z`u&nwzt}N_*SxVHBEfSg${mF;LPkV&cvrw61m-GB-?G;TA3HItUoB|C*tjN zHfEj>5I&I}XQS^a?#lw_81}w**)NYZLiXZMj+0EMt3qCg>&u1A4+!qib8wmaOgL0n@1dkXg)-r} zCaZ-J3bcunYa+};`~)L{QWw-%YA4drVQey&;m(uZZdmdD@22PR?}dr~UpcFOs;gDL zyPqqKG&QCpKzIz-2aMu1I`+D+rJH%Lt$tU9mk$NZ<$5lChS{iw_F<_hSg_lveK*y> z=_j0s@eFvK$stWwlM1}UIwfJ!Hvi|~3~)*n5^lONLbgYH2lu4Qm6RZ4tN%_UYH`?t z&Fm45w4K{7ng_~iADIgkt!(5gDkU&SFUG``etam2A=7Uj1QhVoAE=`}e z*C5B?yA0Dz=s&$1!ijX*gyQ)_4em*{t$p)Q4`n=MRCkispvk|&+~~|9;i+9O^e>%g$5(qq|qR>qsEmyK&;tlJ&!IiSCI;w>;1Gty;>k4JhLC{ znxBwOBs~)J8r-?N(6m7EU1sw|N4SQhk#$FZ3KElYmG@_ z7|+-y)p)!VMlIkcST}ah%|sMknfpV$lLA+m(2U^Ge*%JcHRmLl){w~HmAZimJ{^lKKcC2EcaKBMy%m<7&f5_;vV)za&_zpku z9$bm$vbPE$>@h6Jm>XO^kHw0+F1N=#3+MWaRD^%XQ;5N53z2@l!pH8PQ=#QRVK zIr(_?p331h4q}wIo))-EXkf7Iph~c!Q2c|XDaXSecY;%gk*h^8KRyB!0wgF9u3^clJ%nHZJt_P7Y==u7}5PT+O4J zz5OGiT%NktWfMf_6W?cRvVv{mt|KIq-Pb%ALhRu@>F22W2`_M+i%F6ANz663vV+zrVWXiU);n#5I2DO*&`1dDtJ7 zVil`iwa{8bz5)cEe&958PeD1}yjiji$BcI#=Z+9|qosBDblLJbQc6a5CT+m2R^80L z%G4Hjlv7s6BBiovDZ+C|uGLW};A@i5r9Vj)n~>7!m@GoLuCdj}V$YJeP*&LZbY)0yDaW+cxCk)k0QC}whRqph7&*0Zy3b&~N+5?+GUJHm8|9|6^U>hWp zSiQkSbD$|oC`Ca|_!b3L+L?+U;+PG(%(%6`e;POrGz^btJIol@fp}2rr!UNK_Fkkl z9a0%NIGV2}{lTpn1}y$^2A`=(n9s%22W_3?xJZ!CibcD_r4N;?E(#xpsbc4O?aH`_|uj-&@3eT?6t9ZQtC8`AG&MIlIiMW ziOGh1PoUt2vdh0JjiJ}t3us}i_9euF>|VxJhRaSqRl*xT_8%#}+Spu26gMf9L$5mA z=rakEJf)3RbbV8h&HBEG(xG%#d$5*&{{x}FkCt{^z=KtTe^gj zbN~IS>?gh;oXClxQ~Q()0rG*a*SaK!i93uBQo;VFc@%$iBrrpNVhu888^eFRIc5UO z7FD~SEGCNBIww73E`tz)l%aWSy(aB(T!ps$O%qJDBfb>`ThG$&!I4y=a}377^Ar2) zMl9m2?OMn_{-AGS8rle*ZPoo6p(V6djk1UiX+Q4;+dQBcf7K$ER?zm+O*t zM3lI|Q{GiV%wL2F5gQqFsX7?#R(Wph?#g)#=drbQviy;xfU3#9 z+|95?zo$|Rf@H@~zGbHxxUGFhM+fXu0mnfVdPxKUzg~f4D4*S=;YpYzjwFbN(1LFd zc7Ydul}mN2Jb>`5gC3}Hln}^<53KSgxP3($!zlh*b)ZWT7|}T>nhIU=d^^tLmhWIy za9A6jhV`wmVfc=c971*!Pczlu&Kg*s0a4in)@=CNKd;#mXhK`aP-yNbd^pd?W|`d2 zJUUpdM+$q@g8%~#ppOC*Ev=0sTa-|c2mjHmXUpKA=dbfjk8QdT&0Bb3zqmW!b~z%~)BR zvL)NpXidtEcqz3fKnGXfJURnxLM`gz%lGe2TdA$T1eo#6^VvF|WNO-;4u_+wr{A+f zSWYlQHwK*sFR~^|Li|auA81h`d@9_$4vkB*N_#!_BpUjd+b+ZaJMMTPcM{OwW=-zJ z$1M{A0j3tLewfZ}#0Ciq^fRA&gLXuZm*3BQ&coH+`y4#A=-(kXjP&5O_=uHYeae$o z5HK$J>iE|rNgg@YXazpD_DDk#tSOgjqv)H81oL8Gz9l%vKxfrGkgw5_SA83^fu4GO zdp~pAn|OSixS&?HnxWrrP%7RdP!Kw_!!Et_K-H*7w6#carV)OVXJPh5D~y}y-?x6e zW{1k+{?713V%{`6+*9lUm`8q}Cps!iZjC_=A5>PkRmwW6M%RjalrR4HX3Dz3>zT%i z&`f-Z%4b=FDKG?k_SSYe*MDWWOXrImBeMx_@6Qf+d9r={w#x5C<1dsiK;p9obEr^k z1ev!)OgViexs`2EXypeC?@7z5bu-UHF&3`58TJ9H*#3P1xkzh4$5*#AWT+(jL%!W< zFEo*j6iIraU8%6Q82v&t*jcV$wGB^#0sj)0NXO{(Z-?sP?O*33Msv}0;No5L;gYCq zRMhGo$Z_)E`wgl4lX%*-?3d#c(NS#rP9{C#WC+tPvjxuL>mDo)jSE{~d#Ulh~3+mFZP(yZ>z?`6L?hvmI68v8tvv4t|#+R)f1 zjT3|9?s_pLSvMrw(rQH?OE^L}15_n~Y$}{;JDBq~EE3UeI9MThPF}Hr?gego683pz zB;IEp2=xaKb&I0&1~AB~F!O}tY&@L`57-B<5Y$-r!K*y1W|mV7eguvOi|BDWzd!u_ zRrm>~!iBfViDN38qx|_6*Qk_N43y~`op0)G0v;twvR$F;a@^6M9iGkMT^YlvnDF*F zRAQXf5@&^=y7u+YSltvZHUaadMipJ_7x?dxyS5+$qS->(bjQrBGr-Kh`UKGr@QS|s z%z9a!(6qj)DwSZadbJ#}H{BZ0BG1QP{2{K(tA|+i?r(J9>opYwF@62{JN4;M3#umm6HF;#2{L2aIy9^B&3aIsy?i6Ljk)O!&6HwOa zR}KAw@l{Og>}-29+q9@E>Mk?>up$BIKTu&$`@rXZW$FYLn^BE`b9=(^WixBR>*H!4 zu}VjSm7fuQ=`0>d^deFxY+&1u2A0Uq;sl9}w#gD%7#eRI=>9}zeWl}?8w_;O=>P^^ z+y(B-pqRC6(q$9ibC2@I@7uE*8~y|5XmpvWXjUTG?x;@}MgA}+%$!-;HvKL!9m}~& z?I^!D(Kfeh?sQK@JmYpz3ZyO?@^gcifZ6pyHV21~51_f;k^feED_Q?1qFGTAGnf>3 z`46Yrs=G0uqIkahRBsdYQs=ss=Xv!w1VBE5k7MMTN=XCcmq zgyq;9g#lRInRd^4P;qF}F-oW~7S%_uXj&L#ERI0tg$OVr2{bIaR_|5qFHOW8-r-0HbP#a{a+<1eoXkyx zUJ{e!wGBC}IhFBbTzDQjQ9^H-$3I4#1wuOsiKGDCY*{Ilv@u^VnNdjBzGB53=%Rdd z0hyP%kS`~qtFeP{cYaqat>xMKJ9b&K+b9I8ubT1e;p`Hpp+uc_sZX} zO^`8XPuI)9S%wE(X7ifr*mk+dpcNUo=n``AC8q^XI6?N`)c*ZDXPDec;ln`tiUaU< zIf)f3oj~aK1KN|8AExs0U`b2!fOxK$qqm1M!ZW}7k|h44ZaM90Ln^Nw z>p6^C($QSLEZN!&mTBL%L>^`cCszi-iR!uDL;1CTVx689wO4U3 z4EU8IxN6+`nE2L#5fAx>@|8vfxnXIlEEs_#0yl^>-7Ww6IoUsY^545AX;RWNt>&x3 zJwJw3HZoM1I9gO{3E?*p5*1HhzBB9;Na#uwZZRg|_r7?HR(80|U!k$MdIO>jZjOkT z@eOP9iF04f_!$cn{8Hp!6guCC1FwGNej|>oPqY}0eF+?En(r_FqPivOK*mO-1dLVr zv@N|sC5VY(%JMWGqyG_A&*WYY;fR2sGKlWcGLwD$aMAB&5e#HIr+Amzf9 z{k$LNL%(Z*gOjU2%T8pQGEKbm*gLt*%#2a;@<8QwH@*sQvb}>BdpU$~U>o6tQN1%v z=1XKytev-X;><5U3H1R0D>|0g>RsscX_X7lz^jw^i8p-AJj$_&x9l~7k*0u(w{Jm2 zLdd+VN6nOuj?9364yxzsJ!I89D*lxB^A>f-1Sf8*zC2YWGT-@$?}5I+CH zR@Tz*IfH$4&PgA=aOj%wo835E5{yCQn{k$+DO=ROLUfGmjdMCnS{R-E9DJpb3b0_= zNp+?ctZB#!(sP!eVn-zvybue&7N`C0&nnC(tFIrAz&96Z3N7qwaz*2QL0RgA2z+fJ z)FSO_J1&ejPvPj}{SLO#<+-}83h4!UgWZ1z_J`;|E5#NRo8nyHLI*`$=c0-JafxYC7{4uVeB2S~_jQ+eLkDBZoshbA>_1K4epUcGH zeu{r@vv-h^K8JpdWWFsDLY*C>t+h4yp;TCc8*V|A*F+s5ov65IQM_okL3uOvD9oWh zik6Bj_-@96((v|BWOoGEx9MH%L$2e*1l255L@}MQbaBvn0$ooHW#4*g_SCezR(~H?ImhOkus1`I@1IFsp(v)oqNviamI8VsO|dL z$xN@$j{-WhQH*v|5fsQoo@Sx5hhf{*c{R`|fAGLz{534W?)Um! z_X;`=KT+u-Daavg)(X!s`hbRMoOa8fDl6Invr>5m6&Vj?BC1IPtd8!}VB1s~6>t^N z-_dxuU1^9`=Ulj*=xpsv?9Mfl%;yB+_4Jj$TdAxx%!`zD!EiAn4Z%L}M-PUVI-tH0 zYbkN}p#>i*+J324Bg-3Oc`_q$r&`IKv^#1CQBfICHs1IT-uz$ylzHIBO&tOU_V>2A z7eGuA;6s`PF~KI$e|xggAuCUjjX~8e1Cm>0mdil&2w?JF^EE;e(|M(2i6)vFM3Tn{ zrWTboNq5QQF))szMl-u2zx!C}`Q${x$)uT|&GO`_9-g%nzyFvPB z>|s8Wh1$patG%k?4UGh}-}@r^X*IFDH2@=c+$9~nI<9h}Te=r>{9 z@xvMDQOP!+`#)2Y=E0s}G^QT%8P>V!l@aD0dUmpS~n9KTC=1D2|{!P zyd+kCtcgD@eU1i3nBkHom7E7*3|tdyS$;;mC%7=)^If}Sb{@fqnT5?!C}!72#(#Tb zi04_F0-9YpT8rkPSzBGRzBQ+<9i}%g&#$W+4m2OwTHsl$m>NiSS^wDmD4(p)^M+K| zeHxa(aIn7V@GUHw+{^zQMq;P*Y5p-m*wXwZL*V49WV)sxkD+BzWyb*sLV)8XX zJ0;;pWBUVC9juy-va9w2#Am3#~VavWzu1-;Zmhfn#oY&5sW9YaU%PIy* z=pBC~m~&YY#{Nazztms|Q{BI6bun>M5Z!9UJb_HT)MQVca7fnTKs5gbHf82@TNr=T z^NT%@+Y60E&1S~Xw4=A%5mPOK!iigUsk9(cJ1tDSIlHTYfW?R2H?YkdMthub*tLs8 zkbuE;aj#n4@ugof+8NpRE27{Gao!Rt>9Dw0*sbH21hw%BV=&&+8E7vPl7gW^__#Lq z*MW=yTDG5=8M9B>XqAW~$!N1yqr1Wo`S)^$mIUc%{>-w%p^41g zsf~uThjqb=b9OX`#wb5zr){VJdFY2(3cq_TEC9BX@zXB=Im)W=J(4iy#*gb3zjyq` z_n&W#c`3yZcybx6pjK|N5&v(Y1K?M;a}e}!zXjwen^n%7N;ZSBTFhg)6okbq!zh}vy(M}PZO_ph=A@%#fAt~Bq;qsHOtV%L(PL?s)OmopMa($p|VE4bH`*zW0nJ2tjB=-@RL@b zVt=qw*zwchG^J-5Z9jXoMe#GeU(W2oHDise;FE`FR63SmCCcso zElTS+pD?8e>%c%Hcie)GAO+<&M^vhVpwKq~q>cXH+=9<=%$gs?IsUl_q|V+LR#p*g zGVbp)85mox5QYCM>rWv1mDhZuQ8IdnZp()0~Dt^>736xt9j0+iC(JI zVRrLiixhTkZgOuK!x~|5X)IAx$IhMp6i_+VG{G585fGzbc#3h2LSRJTNN1WFT$j>c5;U$Ii1{z0uD zDu2M=J^=BrW{RASzo5v8X=g<2RfSue7SBD#TOab8|)kF z=a8dl65ik7$e<}<5s}b~DD+ibv>K99u`B}fI+`L44$|h2xMWz9=tA;bjl-9vx!cC9 zpv4&VFVOS+AJ8z67;@Ut%-Xq{zb*ZSlFS4FTyAWr6Kn1pGY`}_6_9Bt2G9tExYYY8 zOOVlmC*L#o#=tIEPqP%ALSh^w71CknU#V5`u6BGP7SFg{ok`svE=kM+HZUB2i+Jn| zQ|PJCdnQ6y;O6HFW}{<~{Kv%`8`$1HBFC$1BylZ68=|sR25&0oo`W*`DpP;gj6^O4 z&G!8@jDcj%nUph{+XhqRSi+^dQ=avt_TTD*Uy4&$=qckav90RUr{qpV%#Wtat41(Z z8RicLN2?|$4H2W}Zx5}^C13o65E7Lwg3|J=NYc!zniBtQSDKFE}og;$d7!vCq=+7q8<*7=ZmC;2^}#!?+=H6P-dq7%lhXSXpVgGIBJHU z8>i~V{)x?kF}*IdsW_fp2u45YM`oA*F1iMn|04A;QvAT9$dVRBJuRdQDxGb|&5=Nb zG2VU_C=KMccPyWEOcAoE$7yeJ0cS!+{E2)JQ-=cJGxog=@+HsS#g?(aroS~VDt;gp zqSAb57h3B-D;J8I>b2hH-1Og@Q;4rYdaWe96%b8UJd8}ymn`55q-1>Uk>NXny@^bW4a;GjANwpsqx$6dNxAL0o<^BX}lp)WrDnPs4 zDjElSKhMr?2Bzy}a%mab-h$nK88Oj&y=g-pg#9 zL-v9JQRuLYA3+<-Wkt%|LXEPatN|hG1GmVWDZE?H6X(?GQRAJhJM+)}U!$=#G+Lgf zl>|UCo!nP*?gGi^s##gU10B#4KQGH46zihZdSZVPn^iTBcCvBVuHr-M8kAV&r=6p< zqE60={YXD{%rK+TU_gqeCVnNqJEPJ=nz(~vVd|RmnP00kTE=(a9Gb9J1>nLfj}E1b zej@(`1~n*B4rlmtxDpmsFN#>9i}+0MIN$z>o6Q{w+1FWS56#zGC~SVqo&Lc8Sc|#;_I9nHuzGq#v18exu;Nd?%NcO%8 zF(=duXm{5m!Tqr+-`S>ar4PM0+tKv_^;^CeG^IGkA5>8bmAfD z!k~|&l+Q#Y*o9iN(tYP#{Z6l(PGPke6L(E5J+$M*0BR3Vtc{j(p?3$G5FyO@8o;z3 zroi~ z%8sL8a(4Egs<~~CyV%b`R86iI%&Mfx*NSz@AW?-6{-I4Zv2!l$X3c2J{C6 zP?=la`_c~mCD7Y$t8Sl$RtN6kbUZDUUk~fMuBBnOcL#HPA})TPJZqk#Znyg{2E36e z8|Y5)7jx$C!M_`yueHuK!vYbT-wSm9xWC;vc@s9k`T{XL;eKcLX;eC?_fh$!(gpe1 zJ0dQ`Un23@IYU5C@MwEC)fWaAB9EtN(Z!>mD)xkV`sw3_m3p|d6<%5nx0 zIUF$qgw}M5zZV7yXY5Vl{3;=A`dxF|VP4;YQi(l(4L<@$S>$h#X|Vo@FZgW(@#N99 z*ilqp^5T;d5bmTa`;4C?~i?>NO0kfzVwFHzCl?P zDHA9O9XR?;z-zIwjAh(HZY>aj`BF^!!79AP8yqcG{==fbaApTLJ=5BxL)XHUyp?K5 zxCM=Q{Ev~ofhl%PZF+$eF$JzJU@De%R9;nfyA;>o9 zVQ3~QKEr-2#c+`wHf-cioo+LnsxcI2+oxztD-=BdwdPx(ZnS81f)`z0d>F=$AI~~B zj@g>Y&^I|d;93@MVqXg~jx&CgDykI;nIw{Y=<@g)mJ9dBV{I%>Emb!Ms=x>W{SV5o z9nLs5DV{ZUk17%`6%;Gr?Js2G22ls`%lYi3Ln>N9Zdt8w-79Zdy~Pw0O*JIlAI-f(R*Gc-s@cXxM(AfSMPAR#T?-8q1CiL|t&(#=Q> z-3%e!H3JgTHN@t9_x=lh>+AZuj`bYRb>G){PBbyvkV{-UEuL4RELvOP6e^C-$w^cw zJ3p|@6-(yx%sM4F(;303y_wEwL{MA>yo zp490H2TYuKTWHBKWKUZN8j=4e!lHt$)712a+9=W3|IgAX1XuFE zUE26+x)l6QvNGoRz6r{IWAi%I_||P6aZD06V}ECFca0 z@39}h$~I^+3k?p13M}M96;aJZJm_QjLE|sM;k+k0o?qhy>Bpko)`2BkxSl)@*$RcY zsm#s!0mkI~saY^zz!x+T&%yZ1TCeXi*fuYVNZk4%``lW?R=L=3c*lT?_+EV;8= zMt@R^_vJ>cC^U)w1G+e4e5KLEG0eCAgc3wdsH(ifdNgOiVTdwtHB0f=f#&e2+133e zy`JONr5F`@FzM7lF5ditk1YQvu z6_{mXF=w=Z2elZ2=jgZ;a1CK&ns9($y*q5u2!VMRN9Y&5EhFBT@I!S??nBS^C81oNv1+=`~bT%gfF_CLU7IhJxr=0gVr=Lu&gHF#@KzTY`Ye{BeS^FY&T+ojsv>F>YZVw1?Mt_C&4JRF+T~?9mYIeaMqh zyuE~}(uMZlCeehSL}o`4=JHXPD>qb-}*$L*95 zZrk-NaFUu=y1f57lZ-Z1@|Z!vGX)HFw?W~)QV+Ch`hn~D{=8>+p(la)-^fiY(f1bv ztxv5i@#LWseDSf?8(WP9GEU#u&bBBLcUTpuNN3zTCjZxIuR zm1&o%zn1|2fomBb9#0N_sEu~+{6hNAN8C9a`I|F9b^Ykw%gX8uNM~$TL-8~qfB&sf zJP*pRRX2LJPP&HD_{fpIXq1HM%)iq~233WC?>ZxXe}4IS)XYxr;iESyg^HB+3b>D9 zd=K(=s|^7^Y%M@h)plR%QtA+M5-L#gc%HegKynC7pvG1~D`#grC@CdNTL+YD4rT8bM3yQ<;9bt@#6!!AmLGrqmJ z1pBNf%5s-VGk$6zlYzbG&qlBtZ_t>Uj?N7>=-Y@yxm6gtCYl>0w8%o&5{Si} zG^iR|sS9&2`Ldj`2a0u|!4vpF$aWZ_4oXz9xZ7S}9?n&hT3A{eSo({NT>`Xl8#C}9 zImKvH34L%)0^$%6S(-u>!^}?!T^D~$x`ycAqmdeLN9h|@Y@SVE&x!qF*Td20(b+q| zX6ld+=Sb@YSPyAj)8S1W7>512ajzpUFo@MxV+_FiELcg(ICnTH4?yq>Wf>Q&+U$bO zmcZyUzca-N94Ps|r7+h-ICB^*W~y#BbEtE>C09@EMqfyCyA~-Fq?-!`$xHDYpy}J& zmQ@Sc_yJ@DtH~Rh+AG`^?>5~{yzw~po>RE@=L&Gy!+W^j^zPSN<_45DAiVY?GCHs2 zt&gFjZ+O#w#n@>OhIIwjPJ@|8(+9=%1;#%VQx$8Bw$yJKkRQS#YS1V@(T zVAZcX@MhYg8$=#P;GlP)RF_V4eSqb6{pai3|50Dw?7QS=(1U#8|Jw4~%lMAPkwmu= zjk^>uIj2d#2AmkY5P?qw*}wM&wDaV|^5ftR!A#Zpi~e{-QrEZbf3&N4)yq$~zvWzT z)#mZhg34&j1l?ywC0xITYhu-^$(wN4+U{Q;a*%U;lF$2yZ6J7op}!`7Xc9xiM8KbJ z@JQ3)4NWA@Oas>8z8>rT3g^f1lk=!$3yl>HT}liu?QSMS$?~Lw^GNf+DF*|wa+U91 zE@(kTR1{5K%A>BsP~$&rsud7vOGSqANqqeR$n6FQeT_oY17WrWK27VnZp;`~)g!5x+@RQ3a)Cu<| zj8Z*wl^#UyJG$IJbPpV^4>}tfPx>gBxoGV^gP`x z%MBbq;A?&)x*u=}q{d32Qt(f6qk76_GCiahVM>3 z4g^gQ-k4yIB`+A2;Tv_*Y_B1pQgU@z%2#Ul3R@pH;$zRbbdK`gn7q069C^s{%BlHG zn51?EyP5hTAmF&%S@h#ZYA>bHZXO<))$ly_jK5vMs%fD^$-l?+J*R?l@qKFD_~I?K zf9_@79SVd>l&s^ikus9iJ*`23o~Wrho|-@Sw`=|a@uIx|mwin*-sl=!umA2RI#h!k_s&peH&q9#n+#)6XPgeMQNk=|{VWzv$L8ALTjO&wdxd)U0 zB%AGJTe-^@{dMe<>1?i>fqC9-L(`7LY(7!K+6OF;MW*9}4|4oahT#+-DknnZdjxq! z33*HNmpxMR@+wm=^82#D$2B+bmHy`0_XHZiyNK?-iBstO0(eT4K)4zW_@*n?%!_GOyF*k%l7)1K$oa^@%f3*wBvxA?0{mievcz}% zt6jG*&oz3QLCsti9v(z~=%?M?fb+{d4l{;uh?avOX~lr@s&o8jQ|hWjcD-U#w8)X4 zb~Q%4N%kerrt(mQLfgCyWP}1>)r6|*ilOF39VB-nP48E$zeVo0edlm+IHh~TXte%qO}>|GPU_0V>XEHoncA- zs0UD$C#~^knS1cwC9&kiy7%%NYgP-mz@!~-B{1~pIqLUfK7ED3i#b$b4*O!$Sas8W zmrG_#%=l8-AasU4QR*i)BpV4&%4CJIS+v(8~@ zpvRf_R&o>+HIobFjr}(+Y{5`Xev((p_wMB))p&z4cw(q$cKSDu=CBrXL4RL6Y!|o# zbPCOK?m+*7m}5B~2~&KBm(4y?=9secBMe!?Khp=7kLkubhkZFWM+cUZgs5u9HQ;XAM@U$}2eZU_yn>>s(o2|M&t-H6m;`lFS9PBI<}@yBvc zZ7Ut#17M zjY)m}2P66R)&2b$u-A1{YsR$hDUitE@3vpnECe5R*Ks#PW#V}{Jf*FvmFiPaHw?69 zASf6nM)$RpHy6UWdlRZ%dTn+p_)r)05j|Ffo?G8+rkGEj2#1DWz7dyLURFgy%KNJ+ z%CE5;1*BpKgjLmus(0r5r=duca%^e`q{xOSnx!>NF+2q z2$7-EdcL1@();v?e_BKr6#1Sl>THhcW~8MvYPdBKMkfOm_KiPUei3*rwcdB#=})xo zJABpTw~JZijMK1hRbBDL4Sz3h3Qq~gESAv$1hDmtT8X;Dl^~It{FeK5!MNa4*C`cc zMh$2ClhDRqru9aijy>rl{qgtr#^Ly&^Gd`Yd))>6D-C9%6oMEcmI_5u0yVp*PG7 zkfOgOBYqckqu$bSVikHvu}q6yEpJbElz-{M7 zi#xrgeqd+gZwtM|_Y=k83IqnHCnBJx;x`0@*fXs&q$^&`=bNJO;$_2=6D*g5 zanmWX7$4R0A(*roCZeqtR3Qec=1A-!R9Y6yLj)CTrqZa(}{O^b# zrh7hGYg@^iQF(1#=5kzk#{0yJ&)3x(|C*7Bg`4%3p1@YfQ6?1`O+pn(0Y z-3P3d9E%QcM@)wS2I(6eyd|={(s8 z18jRF-IgvlY{&unVvOm6?VY$DGq+_$TSCcP>S>N#C7K^_+J7>OavIzux;B_m^e%#I#wK--{IN%YXsL5WF4VcM zRTtgfYjgak70U-WZx+X1MWQlVoyj^r?$swfLgBmqi`B+~wyXpUby(YonSc@S)Et%Q z`fCp9Kd%y)T{OP^8m_9)ageH0*^++^vic3NGOQ!HpG*7R6jEBw# z?pu|>S8(0}=38l+#Hl5^&)1t4peM?t0rVB!Au@t9*V?A0Uh;~KsbkuxLnaP=`pMT} zhIlk@#ran7J8$Bfeny%@%mWqVotx}m)U=;r>*~&(Y&?SCNYa7cLf;qJb#%|ipCw;` z;H@FSpgI4*q0g8CHLA=+$eXqWMddtnUVe#TX~|XIAUJMWS-{Z4mq#J-e%FOvKP6Ec zM?75M7PhY@rf&ge)|etKyQNcT?1ImbmHO>>@~9a1oI%GvgOGvKGE6_s)^>^K#hf?m z(c(#fXDgJ)+b)r7B*8*GQ+N_2Yc?*om5H*FeV| zdi84S1VRPg**6o9<~?v(U0o$e8n?0}V9F#UR;QF4Q{8s}3_7T@eZP<4H^DaeB2Dj2 z0FK!^N7f0ZU}K)Nsq)$6I8>;ZFjC4qe^v|a(x2ua1KYNm`c|3A_ z9G5O5g`p=(emAez64$wlm*BEJ5EHC$U+XV!EX2$3%#Xd$X9&#X&;tm>3@oFB%(k7{Ro zK$%@Ok(qN-g62eBqgPLM1GBj^Huu52bj3Ih#gLKtk9Y@sv~OkOS$fb=?;7Fy zJ+6nbe`@{!u3VRNB!W@X;EHgAI^E$m&xnYA-H|*yvw2L~fWtsKn;&cRR!LH~dn?=G zs?yrbdyA0}Zq`eD(teSkDs|#sE6&9eI2lx9S$3-b_a_Y>ONh0eeSuAk_hXs_(HMTu zaZs%zZf=B;shPW1Fgauyli;w_S4c_-%-;^sa&u zlkbraDvNYGuuUajZ^WIQEmbbX6k!0WR{dPqVR?qXuUH&K5jv6VR zP`3V_w#AEb5gK*QMtUJY+eLspl9)UP6SE&Ux>Xm!f@S$@Ow>^9Iq19UzD6d6lIGJT z;mV;D0hVbE$-l`*?3gDWo#{+KCa$;~yFl%pRKA<_XoHwvY@vQK@Fo@NmVOD`LDDa? zGGT?|nDK0!3lQu>u6XV@P79xxn;*EpftX~`Ce#G#ZTCtM-5>wsdfpawusv}4B4xGHEIK*ia7c4cJhLLJ zTeEwb=CaaP6KF#sHW!+-MzfjwTuH>BTer%`@I4=|!2Huf$YR(E5gE|y6ntIDM19F= zdkM;EBv~?oNgZLY?FOFbOs+rSi(DlM<6VI~e?wg!nibwqwVx(Xbk6=+sX#G^XuS^` zIC23z{d?MH2);)IJoA((5@E6A&E5n*C42sopKcK1B`IezlLpuR{`<@~zH9&<2~yzf zVT;RP?co#xtT1m>!J0jyRJJ&^lDm06OLKWWE?*_AR=ly8tq-ZVdm+=vI+H-sbqai% z`;k}Ijp5HqO9gqEEv|oEbekzs$uR)CwF3^&Hjzm}IE_E1A$oJrGTu;y ze%!a*3~>))h7>mFx7iUbnu$&JW<@NJ+fqHHAH*TxCqmq1J8Y>OJfCh<=bm7oKNAO^ zawsm1^uJfp*-t^+lgL}re)Oa_6V!HsYizHHFz^lpROId`oc`25a$GsQi48Ol?y^;fV>|2(wJb?t>t*}ixjs1?-pcf< zkOVgDA}sa93fI3%1IkH{-tIr#-WVRzaL!Ri%!)YVcWXY&bI&nEJ^{ zZFIOU;K&*XbO@FiTQ-M=Ab-URm9VtFzNTCKUY zt~vq4wMZ18WF~B%&lIAtYaIT_5_{CtIN9GyUiKNWgZGbnJ^muFqQ% z5}%%{j`NbALo6=*LWY`|NKXlge8<46Wt-<0ajISe-a$*g@djRfImZ3HtHyT-8W0-S ziJ2BV@w=7FadD_E6~RTj8xPy-Y}|!VULl+!i2P z-Zk8$$Jd+J>l}rh=CABJs_igWtqNU)H67Ixo>*8_Qupw6-b)BV8v+?%;$xdP#o;D4 zdwafh;~=A`t&YG>FyoQ7k?Mncal6hO^!xw!+r>%an>g}^#lx%h3rh0S72-ZP&E=cMRfQVAE z;H93t9mmt#>T4wBcAcP~;l1XB$w;??4HJVETzzHuT#GG|$!dbNUQDnHIxFX=e3#*2 z81wLv3%jI!yh28Hy~Js{L6Mvb#7A6UBEL=%?_SEPivv)AR|zAihV;#0eeOIj-{=>> z5pK8KH!V3PDE0CCGyY={#bAC=uj)*LD6Ucw^DuoEFaZ4>u6M#YPHx5T2KlcgUL`TK zO3O(UQf}LvKBb!H2DS!vq4oWwYn-H-LP!}U9IYxdcsVt>8st1(rgvybyuv6tb>`WD z&W#lxN5Z~1-SXr186yWdA=cC@ePi#l@$GhZwA-Ah{)7*-v_qK%YYgu%VJZ>PNa)GR!B@zeG+7|Z-GHe^g~_aa5f$j~SU1;8SQb-|0<=h~=4Fg724yZFA=W7i5) zj7){pUUcZl>;`OVzkdm{40M?93cl<88&eb+yhZ(Q_rE=tF53Tl$TJ5$D&B1$T&zWO zDPT;TcIPc#PbaPBPmODbh*eFD^PN|CUN-7-Fmrf3G46cAen0bfMJP)p&E)TN^Ds(O zUiGeyOw7m8VE>7lfoA~bc~E{^>i4%BYS}Le2o@bk8Iwarv5d;G{UC$}Ov zUkH3>ea$!DjsNZtC7K(+-Ae-Nu6Hg0@u`5IM;Y-(O(DS0NBhHb$`eUsN8_*nC$tkh zB1tOB!u>@txHAM_TVlStya8B)Q7{$+b9kI{brJDjh{ zov6XhK9-*a{QwPaPDKmVigR3*Neswe)eSYjBF-@B-)@NXCP$cKQmZ+7_xaHrpZYIX zw@n}zHX2D?1ARU_hcbUW5D?|78-Equ_2@JB41dnw!f-j--i9q<#yYfiHY6A|ec7x` zTC0s3xT35!YKvU1sWwZ=o;gy!Su~-NyI*ZNz54e=u{A@>nZ~s9L&))X<#oyLn6D{( zs95ORs5WJkHbD-G7B&-3zfj+hY%sep5DOw0u3u-eM=;{*mm8@T%mIlHwAI6i?$`cx z#L3+}1c)#4xtfCZ3ZfM(QV#M9GXE9G$SRP-af{!y?=R^jh#t9lw$po*n*r{oJxlfF z87{I^=v;#vKU+lvKqWl!#0Nvsf+_a&wpK*ZeGfIwuu^x zD^XVVjSjJ7HpF`?1c;w1PE^0Dc<704jd!oF~ik%<$e~fjr#9 z2H>CM6_yh!h^Z-|Z^9*33>5$|EaRtp)sOO!Qw6kf0jYWvbQxJ*JFL|4%bjNPw=Sq? z(~aC62~!y-g|c7=irgJVr&l9^I&#Y)0gN_S7 z$|UMpRQrB5MzJ1CLfaU8*=BPwrCojdXG!H4&CdZb1Ix7V4h^^nKl@$9_RX~GR%aui z1|=h_YZTqQeE*4XJ`M33c!vagS%Tl_WWl&rkQ8S|Cvr$cNMsOc%=W6{+!xYP;g23R zAXC3{lJ?tKvXlAXBhv5L@BUC0MiA{ zcuiM(LM~dmlAiX)U(9JAD|LRE`5diMHpezk;i5-HofLxh-GDQaJ$>&T?irX5tAnG; zz%tpyE|MJ=d$K7Epr!hv&RIv~YoVQa(0zY#cPp8=zJlRdzhYk|9-mp0{-fYAtaaei zS0NO3z$nStMVZ!+goiVR7j+;)^1X)51CLD&A- zOC2LfePnK~NM+TWt;&+UdtWO>0}V3Qt|0>w7#iYKH--aAKi_M_kUqzKH_o1h?U*h0 zD7N&wx7(NVvpctS=MmDT911KwuBAgXP+}wEa zrv9t*S=>K4d%W?HV2lxJU2(Ee6&%5J$e)!wbU@jxyMQ;6N4b{Os5%+JwOtPo^woSO zyk>FyRjbt!%X1HCy{9pN=}}B`aHl%MmkbHM&k42RHF%wgy-tWOg63!qE105Q30VXHe4R|u-Y>q#dR=J_uruVkn%!xyP?BN;y!bgrJCB3+rI?Jq zFr&qB{XqapUHcRo@q+@KA|CBLhhm;9T=Z4W@^{ zd|~i}#ZpOCo!?uFZDp`tS7}`Uf4AISug{5%Tx(LwE5P=M)t7$OJIIgFiTJ2N&2h%g z%Z_>1BYP6DXCmp-1g-4-xyF=KbRF{1A}1G3bG3aDjA|r)X4?YHp~1*}Pi&ntf5RL~ zi-FnNd{y1^=^edboTaopOFmzQ0-r@`g9e=Ct);u!Prfbz8E6UR^fX7)II3Rp1ZY$+oDsNZoi_X&4@d^YM9kp< zN#od#8y37AuNywry73~(qyi!+kfTDJjRE}jGZ;~>0B7Wg5SgkGF7Qd4|a|+2l9-0a?Bv>~|2>N7h`vOg0aw$(@P3<~OeA-)ahTh&QBq&?(#H3{R95 z^7Ad#{7nnNQhQ!X2fm0YP~!t$-nXgmbDpL9d zwaL=BHV?eoX9~RAm+_Qh2)=TTyZi}G8{nkmyPT@5+`Ou2aXX5rISm4>>e58vqv8=~ z-Z7e$ns5mRi0A6FPgwqX#|_i+HD4?K05?58H>S#FO=RvG^4AZK97DW-yK6h>S2Wku zc^d;n^~?u!!?u~Ke-ag3zxh1omn53$Q$dO;=FHK@gmXmHM!u1EXlh(EXGv;98$-$P z-H`I~d&GA9UV!m2vh3gV1b*7-JJ7M)sePdS);C%D`)u0$BmRjI_fj(q<7z9x$(t~V z+i>j&RZU?DA4v-y|99Ivrxa^`2Li$O6ErJrPXva$)SUqbXe)ucoWZ*ZRIT;jdjSU{ zyiSW09H2h?2J4U>-`3w%Zcf>59p(u7?Fe4B31*eOuM+ir4T^XW=GRa^{Dn@TT7G(f z2G-69R5uMpndsR$-~0{9tT#?B?~WJUx)GSU(Xh?9q!>!bx>q|<<$_AuNjgkX0M4iu zR&O_8FBCKrk?@FT`+oibXL7v~4*lpi(E_FrGc@PXBCRF$=)}s;SAPjN$@cW{+@c_I zHF;O~3D>eC2>p$ty3eEjDQOh{p-8K_qNMs&6lU$-pymVe{b2a>em7h8Mb!xSD~guT4mg|h+@dgjgg zwT)d_;Gt3mCvCytBBG^OtU@7Lw<9)R&$4i>T>=u?t1#eo1VEfNaj%PM?sZ~6bVBHr zN;1l})nuX2^+ZD%x$XadD zc;J0Vlx1Un9S`}D914zbOc|Y_ji0Ga7COK}D;*RyxQ_`awktYyHG6LjJk56RR3hCM zGvV0YU4Btnv(zrV2@q5%N<9;J9+)I9^9&q-J5E+e4NTKKs=o zS+CHYv=e0e&5sazDBBiz0pAkQ5t~vAVI>R_HPCuY;2TY)1nmZdCJy_%a~nzI9T4N! z)lmnI+lJnn(4TzxX;&ic&<_5jXlUaOFe))Ku~NsmuN&)iXRvWl=C-YVZ9Wv7?)_l{ z#bAV%x382F_Z@eZ);8YK(uYRtdnt1JIY~p9=KlaxOd}gqk(lq>o_YBw=>;8 z(0luGs=}8x{_c^DJlY6(1Si8vgKG6P;6`qb4qJg$l4x0wx|yhSl%H`3zA&)G{@dmK zK-0PvYpkmZSia$3pSw2j5We4eevdyGYA-VDw}Td& z|Ax8o`J6IGnDIWR}G;w?Y2+YPxSdj;<2LqXrXz4oEym7o55p`8>qwzUvKQD}st#YXi z32m3zqK?e5@j|D`+fez}9w&Dno?lqeJhcFcP!1wed|$eJKy`w}IPQQ}Y3jttjwR(`{p3j=&Re+A!u};sJTU5VIB{P zmbuxplj-iQtK!yuw|uJtQo@zL;Sb{VbD`o?ZhHn#l|;N;e}mrUXTB*U$IOO}P&y&h zn&mCw)4h-QU`_-IFIbWSlYHWE}fGUci7=MQO^oW814H8 zZq$0pMK&1p<%EJ;VH~KuO(}ho11xvQ*Wg!k$8YOv?IiJM${J#}zmaFh05RlKf`)<9 z)4uG)+?D*8O@KYjK1XS+7nq!b0WBuzlw3h~He}bdjeCXxzK92+3n}ffJCQHK`p>DT zY=KKE>X3?@WFxdiwg1jOX5QxFC7pR@JkEn|tJPFdn_^05~p($>Ln|7`|qV42zxZzgF?g?6Hjh?C?=rmaEqL3C0}IVF4bd}x=g=rQfL_M{3iS|Nz61mt9h`DA#rJCULIof3*xMH zKN_WUtf7G9x>LjRp=&(trCS}$f1JX&Sw!YDzM1>bdjG=F#c6v^$IRx4RaB2iSWiqK z>xh58e*qaLDy21G%BkaoV)#;0wNh+@RJ{HsmR?E|7#DxXDg#|bgbH3UJs&Ke_Rvktg-N@05_;m=C1*c*R1Fo zV*(vgyoMj=*eLVe-j_Mx<#7_hyI-l`ZIJaY$V^H684-p1%it(}44gwjhdla^OTH;# zCeV(^B^m$DOV1K>O@5>sX7FJsNht7H!vhzN`k;5EvF#cc?4b>g1!~Si z5VLsr=NTX_zSKSSfozo*sm{InzFOlpuufm04sKBao((}-2^MO1!9W5T~ z<6pCyH&RipcRhHrw?DwWy^0fMPGG$=_0B%MYSey9Mhguz<$*3C2`KR|(s&lIBtX>- zWTQUB#M;A=GVM43h`yc4DE&huN*gYjG>p8qOCViAXG6SjkD0^-HhU`8T{9T2#Cc$XT>&rT-3 z4qTpLi$ohBx9Mqm7aluo1gy&D-yDpe9Tt}t$1$dDmT(&RlsLEoBE7>3SJ9Q(5jQ6S z%(9fS4_*i)jyF*MwV1GbcAG7>K$kgjN8S{;GqRy8dP|1I%ImCjl zEc#a?f$r^neqP>IK~QYBrRBy?Nts)(>HT;xCT`Uy zm=Jp7YE2G!79DsYAM63|20Ot`^+kv(NB$aH022RVS4i$>gF*dY5OO zN}L@xyl9N#^KBl-1?N$3!HFQEItx?`APd5uBYP%S`Yv71op>;Wjll)wfvGV16-)c>lMf~PN6$R zNaB9kI%FOwSni>FoGQCnT@Rrv3jVT^_AYfkJLfef4+_qs6X|?w-w!|!b?$|mG{_%A z<}g^G+ci_nvXGgAi9%!22)13Z9tbdf7~t}~FHd|XNMA7b1^gq$rM3y-gL+m@IveV1 z{H(0?;23BkD;**cR~32XBr>3}{?lRwkyq)O_W)RHJI4&UVe>gLbBRu_X6WjSY)N2WN<=P3vSl+6bub0oqYSBWWlKkLt zlDS+Ndn$t`il2vC0ut zl^&#vpZm|+%`&8efCOoT%Bs|{3lMwH4o&3b9svAzjSb zevE(XgBWzuJ!Ea5Loec^PHQ+h!ryTXA#Jm;VDgHgEBsZL?VKp>r|_5uC15dEBL`VNhC|!(ej3%>F@sfS7zS%_~6%UTQG>ih^nERdVR^yyxmG^o{yj*lk!DTyOUl zxNRBX#%w`Ny}ZoQsbSP5Say2~7HvI$YYCq};`GG8&W%whvO|#KP{$o)QX*#du3ol3 zO)&(YgiGBpnC7ob3{0I8S0rGrBb7m7CPss4Rf3}Ppg+GzIlWKxE!62!1I7NL*$NB) za{x&YJ&}=Ts;dNg3N{5ZIq|Int2>4~ja!i1lda(}2u70e{b^RYnbUeDi>;{5!f)B$ zJIQnQ8oIpHu}n4$qxqPKvItMyP(Q4j_c2c|xGgoPU*A_5J!ey~bxkQ7oF4TkW5?d3 zdlK>)H$$gC(NGel;@Yhp=q&uxMBtqBKC@S8tq(-r))D6`+eVQ_9@6y%uqBc4rt!)4 z6(!{7=e&_mZVaak zpv5c4d@=5=SJY94ORU98f3Fm}9--t=V=#WV|EYND<%z*y_stopKd1a~+KcS--kcsR z7}XKYlBs-(_LUgkl;jT@3L~KANp&pO zBV#QjeWx87cH#bENI-$um;EI;Pln7co|*6Yil9Cc$>o=Kl^pnCtD!)T{<4Y7 zuP#(R0X3&Fbn`;#LO%s5W9Y#QxI_lQ1&(nNG7zsvc5_0VMuOFiWcM&Ps{f%h;I^8$ z^ib0j8pOH&d*sB!OU%^9I1E3x*5bju__YJI@stDv_uorJhzEoo5N4yHmuK?p^dVm46yIRQD-(7Uxeu@bl6KV4orNS{G(=3~E zSvmaH!Osv|ypp$>@?=EBzSc9l1ccjW>SbDoeCD;e0*kc&R81A{JOEy-8-X2WS8uKa zKIaSq>nwg`)wW^=YRKCF(NiAYnHvhD4Uh@^+>P^F8)X=Lom{hQLph0 z2E4n)PH`NPNZq#pPI3`rU))m8&FR*?TE^6@`$Pa<`r=h$a~%=E4g;x2^f%~oWeQ!p z7LWTW+d}~E6OLo5ym+gh%mnMdYDpYK<70t8(TB%K;YZu`<5>Xq68iaUSRc<<$^?Tt zMoxEDddtlN2jb7G{gj~|R;2MSw++rr_x=|AQQkMT!sFTMYIxm=Q@gG{j<*7MZ)4y3 z2laU+-fE`j{pIwv|3j(^e2K;+|3TzttHQu^rR=|!*}9zmx10Tg`p;nJtm)lioHKIeJtlm-XfVD%#+Mz`?}~R*3^WZ)?=8#Up&!Eo z919=Fx7cJfHsx-#ty64FdW2+7k%$V0_V z*MpqGK$zepbLi(1`3Cy>e;TwL%zh5r_E_SQJCE1g+@sK*m*nJAN`=3|tZo*+;s4fy zpd0;W*^mTq0g}23s?al$KP$DjL~tGiYg-vxJhR=}(J$IaqnQrK-h8-=pXjqAkj6q4 zG86cWI$oL2C59jtW!q=~it!hRkZUgLo5@^ce2V5oJj@3N#fGQI2A}o9PUj5iHn)@T zCn@KX*L^9P(#WPH_T6eUAox+}@@E5jCcRe^?O^Sq<`>8a8;2WiMdED=Fl+k3QxX6l@iNraVix!=qr3B2Hau#tt{gd9>$Tu=DHQ zNlYUWfgdVyY^e#03J|pu)gAB;K zDZ0dyTZHlb`T8T)|0{d<9zOsOE#V5AtUU^#uG0=wz7AO>K_XZ6=;2I1U3rBuyDGcr zsyp&BBtX}mGVRS_`J|-Iz*9mJ6c-L>am^a#XT%u_q`d_1vDc@@Engvrh68jUB*E$~VP-$g^Tkfs!|%=6Y{{sANsw3U z(b04JQ1Z1ravk}Z(B^+QI|sH*xNr++YqD+IZnACLHBGjy$+jlDCcX7$+qP|<&N=_! zd;Y`T*R%Ip>s~`73Se2_kX~;8kip~F%?NHPqaNmRWMRJna&`4Z8Dvf0?5nfLXIcEC zn|xqr|5Mf)E+1DJc7@>P#|X}+;TQ17rT=`NwB?|l6D*!?+VzBCSFGVDvfAC;s1~CW3s50KJJB0;1teDv{h!|1-dpN#+OY`?vES)iR2!sskrHWd9(|T! z`pxAZ1->cm{^HO&wwGF8Nxm1c=efh*#(Q=ao)8|}at8VYZ_aIOo{AG7_SyOzKRC${ zErq9})1M(hm(Eh6Dp>qj!P&eOjxjB;S2P&Q?gUW;>!%8fHwaVBsSx-j92k_y`nFQ% zy{JP!2q+Er&~9}m+j$SD;YP**IfNqV0L%|wH=aTbC9A3hgn7kV;EyxeD-X~@de$lZ zL!DavhMRSB{_J~FBaNXja(sn@N}Q;Oz<6U$WaZwyk-fo8_&hWu!B@ zAs`|=l#$Ik2`{+uVt>qLK!Rz;kYn}3?6VP}8|nN!ihz#{^cWG8-vtpE91f_R;f}wV zKLoNu(_p|4rm+)P3GcZnEINCUHrt5i$tY=eg{YW@Ur=HrK&^A-20#1t_w%wdH__xd z;xX$q8kEM`#w6jc4RQXq^sQzBmcaJpesygSX81uw zrNZ#XL6`UKkd*o^(jGz$h+WgK1LVpJ69XnJ?kgiB!)ef(vP&R+N)er6%CuRw<%pep z;#}h1zz-P$t7nmb5q`;BW~vm|t+5L-%8PKa!+O zTtfno(&w3qrc8wPdmER|aA2}ms3}R+C&*}-ui)CF-}o`8v!?F{+!|K%XPmWjTtiO<_L9M;^NYcPK-oVwaM#5up*(mI^)U-NDWdHs&^ ze!9GinPscjsaAU)$E`7R%wHL=4-11r)iRz*X9@G}!tteNX|C6Uop|~a?3)X~NpH+} z`xMSYZL1IHDt3z*VtGVXm_Bh!M_aQKVx4Z6C>qi0iLI{Ym_G~5*!zIC=l8h}c(D$_ zee$=ogimAQP;!K-a*bT6ZI(d7z+5q@FcOXig^vcfLMHPTT;TrEAJ5QOVao<>gnHzg z&GvirIo4{{@VR6=!Et+`&u9F1{NId@-#G>{WWl@dg20rPx{&*iKe=$Mx(;7h-M+mZ zr|T0`ZAPbhE?w)&QBZuy8#?#3lc3`bWP)Fk2X`V3^YwR6jI*=v3j^QZ#xFiSI(yPT zvsvqM>%l9rhvUJ?CiY(uu;l|(ehlBZTRH zcD1Bx(s(jl9IP|L&oRs_=xvSFl^vALo7hK3P6(J;^AT{%fRG~wvT#^&F*qfFZhowU zKM#HFhkG1N()@maYN_1__=}D*osi>9)MyrQ_)1IL{0}rvt`zodbnkv2qF1XR-{#v6 zRJS$Qv?Y$NQ154ow)HuA*5-M}YB2}4tGx?Q9|cK=V5Vfs0p&ahf{?~9T03|L;y-c5 z_manp3Jx0kV>y0|6V$hjZ&l)++~1QVa^x(aBrIdB1PNV8@|M3_?XUv^Phs zaTx%*6xmAyB`UE<@>+$9i4mslsP#H35D_X`6xN(Y!4S}lqOUoFY)1odAxKG#n%bCz zv0_K0jJdO~aX_13e$)5;Mos5z?+l%QnU?@CgV{+-V4ich2Go;-m!krbW0;sgHTG}W z_GQt|iCSl_2zF*RzapTYKJn*_acCWkxUGs7hqJVvAD_DWUTTb(RWQvo_YSgiIzUVy z?8yC?Pr=?gFli~yj&CUHa#s4gcRfHSRB#kRb{<2b1!Rg;dD=2N;V8Cm)!_-yrzdYr zYpf~f<}l?b^Ha=bEOB>tk)iOZ?reL7J0U`nEm6{JFgLkyX%U`LQ8e}g)P|d|-mIHJ za&f+4E*=nJN#kNcekBM$%T}hL#^Nl856c_))9 zdH?W83S%7UH5(32K`jOIp$0JAR!&(qn_!JhXJ=OQ;oQ~(&*|`+Qg!RZPdCvWr@c8^{+&;zQy^^q|a50qc^}AgJQ6(Q(z?QsBG0$NBk4_^G;!J|HQQCv;N+*?>;0a zUG1WaQ@5V|jF#Zlhj7L#Y55FvW_(>Dlosv8Gp2?M&NT-xe3%txj0#Vy@k5Xtd%&#R82_Mx4@M{f!T)|OjPyA@fUi(E|bwiJ($$YqL2_!KU z_^DSVdLZ^Qg*9pdpHgo*nXLO3V;C~5NF{q^8^Gt~S?kjgPW%wok<{A=wl`1EQG zOSncJZUJp$Z1llGEYRF<8zRzR7{?|BL9q|=b`EwVn$;$zmUtMS82Q@6@_hXK`?y}` zjz5X8=O!7>?^f&9LM;My4gza*s%JJWk7svin+|v{{-jONvwpE>EgR=$@$tok;>X4P z?|UI{ZfFPw&lQ{(EnqW1!OO=dXd}F%?P)-us=8)pE|&IEE#BG5DWXd<9^2nHmkAnb zHg!+Owiy?9BJ73EsM)J1Fny$G&KfUWZ@5^^xIX#r;V4gt-Kj6Vmqw8CjrNSqGT|p6 zN%g+{+cxbiHgX8HaX!7=*sd}(IEZ^Xfx9Q{6Q3(A zq-74av1%~1xJbG9EKs1wh_f|cdM&4b>p9~6(!$CXP6mr7AQX|w z2bECTw)DfGv)$x<#V>r@Ygw?+ahQwn2Co_oUQHEA?gS}k)?iRQP{4K^^~@3s5n=p^ z&)W&EgyD_hIy%^+$VXEqCHpHgCEdxyATtx2{ev1lO%@rM6>Ej>#2@xOiwCGPXl-|h z9|8wDDb4VqoeNBg|0p>baoqW`Sk3k4{Fov<(L8*4f-F1tw|K6cyY&}Q=4A`)xo!VX z?T#N`mH$tA)&2(J;^@tbE3rfJr~P>Bd{aCjdjmK8=q!!)&lM~w+1mUIzqMwN%e8ah z_Zt&XlE$lJ00>2ULp3#DqtSzL_6GACoNCm<0ch7ip+BpD!*jjtq7hGm4v}p)>jD;r zMSp%

  • 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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..7a361cd --- /dev/null +++ b/authentication/filterset.py @@ -0,0 +1,29 @@ +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..55ced35 --- /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 Response({"result": "این صنف قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + # 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/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..8a99dd3 --- /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=hamedan&password=ha123456&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..30acc75 --- /dev/null +++ b/authentication/migrations/0001_initial.py @@ -0,0 +1,373 @@ +# Generated by Django 3.2.13 on 2022-12-04 13: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): + + 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)), + ('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)), + ('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='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)), + ('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)), + ('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_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)), + ('state', models.JSONField(default={'birthday': '', 'city': '', 'first_name': '', 'image': '', 'last_name': '', 'mobile': '', 'national_code': '', 'national_id': '', 'province': ''})), + ('base_order', models.BigIntegerField(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(2022, 12, 4, 13, 13, 23, 181362))), + ('last_party_date', models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 13, 23, 181450))), + ('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(2022, 12, 4, 13, 13, 23, 181666))), + ('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(2022, 12, 4, 14, 13, 23, 193330))), + ('time', models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 13, 23, 193389))), + ('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)), + ('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', 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='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)), + ('name', models.CharField(max_length=200, 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_20221204_1315.py b/authentication/migrations/0002_auto_20221204_1315.py new file mode 100644 index 0000000..df331b7 --- /dev/null +++ b/authentication/migrations/0002_auto_20221204_1315.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2022-12-04 13:15 + +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(2022, 12, 4, 14, 15, 38, 825842)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 825907)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 815252)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 814964)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 815052)), + ), + ] diff --git a/authentication/migrations/0003_auto_20221204_1402.py b/authentication/migrations/0003_auto_20221204_1402.py new file mode 100644 index 0000000..c9eeb6a --- /dev/null +++ b/authentication/migrations/0003_auto_20221204_1402.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2022-12-04 14:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0002_auto_20221204_1315'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 15, 2, 52, 979208)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 52, 979275)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 52, 970253)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 52, 969944)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 52, 970013)), + ), + ] diff --git a/authentication/migrations/0004_auto_20221211_0954.py b/authentication/migrations/0004_auto_20221211_0954.py new file mode 100644 index 0000000..a165f37 --- /dev/null +++ b/authentication/migrations/0004_auto_20221211_0954.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2022-12-11 09:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0003_auto_20221204_1402'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 10, 53, 57, 373969)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 374005)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 365502)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 365200)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 365270)), + ), + ] diff --git a/authentication/migrations/0005_auto_20221221_0001.py b/authentication/migrations/0005_auto_20221221_0001.py new file mode 100644 index 0000000..4ca0b25 --- /dev/null +++ b/authentication/migrations/0005_auto_20221221_0001.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2022-12-21 00:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0004_auto_20221211_0954'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 1, 1, 33, 643309)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 643340)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 636973)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 636808)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 636849)), + ), + ] diff --git a/authentication/migrations/0006_auto_20230603_2204.py b/authentication/migrations/0006_auto_20230603_2204.py new file mode 100644 index 0000000..74fdb7b --- /dev/null +++ b/authentication/migrations/0006_auto_20230603_2204.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2023-06-03 22:04 + +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', '0005_auto_20221221_0001'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 23, 4, 2, 197322)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 197359)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 191071)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 190914)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 190976)), + ), + 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, + }, + ), + ] diff --git a/authentication/migrations/0007_auto_20230603_2209.py b/authentication/migrations/0007_auto_20230603_2209.py new file mode 100644 index 0000000..845591f --- /dev/null +++ b/authentication/migrations/0007_auto_20230603_2209.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-06-03 22:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0006_auto_20230603_2204'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 23, 9, 47, 941746)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 941784)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 931752)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 931502)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 931592)), + ), + ] diff --git a/authentication/migrations/0008_auto_20230720_1546.py b/authentication/migrations/0008_auto_20230720_1546.py new file mode 100644 index 0000000..468b05e --- /dev/null +++ b/authentication/migrations/0008_auto_20230720_1546.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-07-20 15:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0007_auto_20230603_2209'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 16, 46, 30, 505080)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 505115)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 497504)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 497357)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 497412)), + ), + ] diff --git a/authentication/migrations/0009_auto_20230723_1343.py b/authentication/migrations/0009_auto_20230723_1343.py new file mode 100644 index 0000000..1bdb674 --- /dev/null +++ b/authentication/migrations/0009_auto_20230723_1343.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2023-07-23 13:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0008_auto_20230720_1546'), + ] + + operations = [ + migrations.AddField( + model_name='bankcard', + name='user_bank_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='city', + name='city_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='city', + name='province_center', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='city', + name='province_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityunit', + name='city_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityunit', + name='city_unit_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='province', + name='province_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemaddress', + name='address_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemaddress', + name='city_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemaddress', + name='province_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='city_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='national_code_image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='province_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='system_user_profile_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='user_django_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 14, 42, 56, 164258)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 164295)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 157005)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 156867)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 156909)), + ), + ] diff --git a/authentication/migrations/0010_auto_20230726_0957.py b/authentication/migrations/0010_auto_20230726_0957.py new file mode 100644 index 0000000..c10f71f --- /dev/null +++ b/authentication/migrations/0010_auto_20230726_0957.py @@ -0,0 +1,134 @@ +# Generated by Django 3.2.13 on 2023-07-26 09:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0009_auto_20230723_1343'), + ] + + operations = [ + migrations.AddField( + model_name='bankcard', + name='province_name', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='city', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='city', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='city', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='city', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cityunit', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='cityunit', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cityunit', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='cityunit', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='province', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='province', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='systemaddress', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemaddress', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='systemaddress', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemaddress', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='systemuserprofile', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='systemuserprofile', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 10, 57, 28, 736632)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 736669)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 730496)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 730307)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 730345)), + ), + ] diff --git a/authentication/migrations/0011_auto_20230806_2224.py b/authentication/migrations/0011_auto_20230806_2224.py new file mode 100644 index 0000000..295739a --- /dev/null +++ b/authentication/migrations/0011_auto_20230806_2224.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-08-06 22:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0010_auto_20230726_0957'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 23, 24, 55, 531753)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 531789)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 524587)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 524430)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 524462)), + ), + ] diff --git a/authentication/migrations/0012_auto_20230827_1543.py b/authentication/migrations/0012_auto_20230827_1543.py new file mode 100644 index 0000000..d1efedd --- /dev/null +++ b/authentication/migrations/0012_auto_20230827_1543.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-08-27 15:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0011_auto_20230806_2224'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 16, 43, 3, 915052)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 915088)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 907540)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 907398)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 907432)), + ), + ] diff --git a/authentication/migrations/0013_auto_20231010_1504.py b/authentication/migrations/0013_auto_20231010_1504.py new file mode 100644 index 0000000..3310975 --- /dev/null +++ b/authentication/migrations/0013_auto_20231010_1504.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-10-10 15:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0012_auto_20230827_1543'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 16, 4, 25, 261530)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 261530)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 261530)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 261530)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 261530)), + ), + ] diff --git a/authentication/migrations/0014_auto_20231112_1546.py b/authentication/migrations/0014_auto_20231112_1546.py new file mode 100644 index 0000000..4475ecd --- /dev/null +++ b/authentication/migrations/0014_auto_20231112_1546.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-11-12 15: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), + ('authentication', '0013_auto_20231010_1504'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 16, 46, 2, 555876)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 46, 2, 555876)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 46, 2, 555876)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 46, 2, 555876)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 46, 2, 555876)), + ), + 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)), + ('payer', 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/0015_auto_20231112_1551.py b/authentication/migrations/0015_auto_20231112_1551.py new file mode 100644 index 0000000..db5190b --- /dev/null +++ b/authentication/migrations/0015_auto_20231112_1551.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-11-12 15:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0014_auto_20231112_1546'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 16, 50, 52, 82371)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 50, 52, 82371)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 50, 52, 71081)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 50, 52, 70079)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 50, 52, 70079)), + ), + ] diff --git a/authentication/migrations/0016_auto_20231205_1348.py b/authentication/migrations/0016_auto_20231205_1348.py new file mode 100644 index 0000000..18bc8fd --- /dev/null +++ b/authentication/migrations/0016_auto_20231205_1348.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-05 13:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0015_auto_20231112_1551'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 14, 48, 10, 308577)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 308577)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 276606)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 275608)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 276606)), + ), + ] diff --git a/authentication/migrations/0017_auto_20231210_1416.py b/authentication/migrations/0017_auto_20231210_1416.py new file mode 100644 index 0000000..09d2e29 --- /dev/null +++ b/authentication/migrations/0017_auto_20231210_1416.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-10 14:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0016_auto_20231205_1348'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 15, 16, 16, 775906)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 775906)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 771906)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 771906)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 771906)), + ), + ] diff --git a/authentication/migrations/0018_auto_20231211_2019.py b/authentication/migrations/0018_auto_20231211_2019.py new file mode 100644 index 0000000..f455e33 --- /dev/null +++ b/authentication/migrations/0018_auto_20231211_2019.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-11 20:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0017_auto_20231210_1416'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 21, 18, 56, 673292)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 673292)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 667096)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 667016)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 667016)), + ), + ] diff --git a/authentication/migrations/0019_auto_20231214_2314.py b/authentication/migrations/0019_auto_20231214_2314.py new file mode 100644 index 0000000..7a94952 --- /dev/null +++ b/authentication/migrations/0019_auto_20231214_2314.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-14 23:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0018_auto_20231211_2019'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 15, 0, 14, 40, 758169)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 758169)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 751949)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 750931)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 750931)), + ), + ] diff --git a/authentication/migrations/0020_auto_20240108_1233.py b/authentication/migrations/0020_auto_20240108_1233.py new file mode 100644 index 0000000..0f46caa --- /dev/null +++ b/authentication/migrations/0020_auto_20240108_1233.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-01-08 12:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0019_auto_20231214_2314'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 13, 32, 58, 374438)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 374438)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 374438)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 374438)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 374438)), + ), + ] diff --git a/authentication/migrations/0021_auto_20240110_2021.py b/authentication/migrations/0021_auto_20240110_2021.py new file mode 100644 index 0000000..142e96e --- /dev/null +++ b/authentication/migrations/0021_auto_20240110_2021.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-01-10 20:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0020_auto_20240108_1233'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 21, 21, 13, 768583)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 768583)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 768583)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 768583)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 768583)), + ), + ] diff --git a/authentication/migrations/0022_auto_20240131_1501.py b/authentication/migrations/0022_auto_20240131_1501.py new file mode 100644 index 0000000..afc089f --- /dev/null +++ b/authentication/migrations/0022_auto_20240131_1501.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2024-01-31 15:01 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0021_auto_20240110_2021'), + ] + + 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, 16, 1, 33, 609274)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 15, 1, 33, 609274)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 15, 1, 33, 604279)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 15, 1, 33, 604279)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 15, 1, 33, 604279)), + ), + ] diff --git a/authentication/migrations/0023_auto_20240220_1536.py b/authentication/migrations/0023_auto_20240220_1536.py new file mode 100644 index 0000000..810d62c --- /dev/null +++ b/authentication/migrations/0023_auto_20240220_1536.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-02-20 15:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0022_auto_20240131_1501'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 16, 36, 25, 342295)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 342295)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 338297)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 337302)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 338297)), + ), + ] diff --git a/authentication/migrations/0024_auto_20240407_1100.py b/authentication/migrations/0024_auto_20240407_1100.py new file mode 100644 index 0000000..e265c74 --- /dev/null +++ b/authentication/migrations/0024_auto_20240407_1100.py @@ -0,0 +1,61 @@ +# Generated by Django 3.2.13 on 2024-04-07 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), + ('authentication', '0023_auto_20240220_1536'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 7, 12, 0, 37, 741325)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 7, 11, 0, 37, 741325)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 7, 11, 0, 37, 738325)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 7, 11, 0, 37, 737325)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 7, 11, 0, 37, 737325)), + ), + 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(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/0025_auto_20240416_1516.py b/authentication/migrations/0025_auto_20240416_1516.py new file mode 100644 index 0000000..be0f5ec --- /dev/null +++ b/authentication/migrations/0025_auto_20240416_1516.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-04-16 15:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0024_auto_20240407_1100'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 16, 16, 37, 407531)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 407531)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 403526)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 403526)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 403526)), + ), + ] diff --git a/authentication/migrations/0026_auto_20240417_1455.py b/authentication/migrations/0026_auto_20240417_1455.py new file mode 100644 index 0000000..65dbafd --- /dev/null +++ b/authentication/migrations/0026_auto_20240417_1455.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-04-17 14:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0025_auto_20240416_1516'), + ] + + 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, 15, 55, 11, 648139)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 55, 11, 648139)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 55, 11, 639145)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 55, 11, 638144)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 55, 11, 639145)), + ), + ] diff --git a/authentication/migrations/0027_auto_20240420_0047.py b/authentication/migrations/0027_auto_20240420_0047.py new file mode 100644 index 0000000..fbd4823 --- /dev/null +++ b/authentication/migrations/0027_auto_20240420_0047.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-04-20 00:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0026_auto_20240417_1455'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 1, 47, 23, 720070)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 720070)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 715068)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 715068)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 715068)), + ), + ] diff --git a/authentication/migrations/0028_auto_20240427_1523.py b/authentication/migrations/0028_auto_20240427_1523.py new file mode 100644 index 0000000..e878c1d --- /dev/null +++ b/authentication/migrations/0028_auto_20240427_1523.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-04-27 15:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0027_auto_20240420_0047'), + ] + + 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, 16, 22, 34, 278366)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 22, 34, 278366)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 22, 34, 271367)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 22, 34, 270372)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 22, 34, 270372)), + ), + ] diff --git a/authentication/migrations/0029_auto_20240513_1607.py b/authentication/migrations/0029_auto_20240513_1607.py new file mode 100644 index 0000000..78cadaa --- /dev/null +++ b/authentication/migrations/0029_auto_20240513_1607.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-05-13 16:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0028_auto_20240427_1523'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 17, 6, 56, 491299)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 491299)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 477303)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 477303)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 477303)), + ), + ] diff --git a/authentication/migrations/0030_auto_20240516_1516.py b/authentication/migrations/0030_auto_20240516_1516.py new file mode 100644 index 0000000..c24792e --- /dev/null +++ b/authentication/migrations/0030_auto_20240516_1516.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2024-05-16 15:16 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0029_auto_20240513_1607'), + ] + + 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, 16, 16, 2, 171521)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 16, 2, 171521)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 16, 2, 167521)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 16, 2, 167521)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 16, 2, 167521)), + ), + ] diff --git a/authentication/migrations/0031_auto_20240518_0955.py b/authentication/migrations/0031_auto_20240518_0955.py new file mode 100644 index 0000000..b8dbf05 --- /dev/null +++ b/authentication/migrations/0031_auto_20240518_0955.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-05-18 09:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0030_auto_20240516_1516'), + ] + + 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='pay_type', + field=models.CharField(max_length=200, null=True), + ), + 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, 18, 10, 55, 13, 145830)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 13, 145830)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 13, 142830)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 13, 142830)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 13, 142830)), + ), + ] diff --git a/authentication/migrations/0032_auto_20240527_1504.py b/authentication/migrations/0032_auto_20240527_1504.py new file mode 100644 index 0000000..6575596 --- /dev/null +++ b/authentication/migrations/0032_auto_20240527_1504.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-05-27 15:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0031_auto_20240518_0955'), + ] + + 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, 4, 11, 379226)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 4, 11, 379226)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 4, 11, 375226)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 4, 11, 375226)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 4, 11, 375226)), + ), + ] diff --git a/authentication/migrations/0033_auto_20240620_1609.py b/authentication/migrations/0033_auto_20240620_1609.py new file mode 100644 index 0000000..e1ad34d --- /dev/null +++ b/authentication/migrations/0033_auto_20240620_1609.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-20 16:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0032_auto_20240527_1504'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 17, 8, 52, 783409)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 783409)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 778409)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 778409)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 778409)), + ), + ] diff --git a/authentication/migrations/0034_auto_20240713_1535.py b/authentication/migrations/0034_auto_20240713_1535.py new file mode 100644 index 0000000..e84e6ac --- /dev/null +++ b/authentication/migrations/0034_auto_20240713_1535.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-07-13 15:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0033_auto_20240620_1609'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 16, 35, 11, 366844)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 366844)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 360844)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 360844)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 360844)), + ), + ] diff --git a/authentication/migrations/0035_auto_20240803_1454.py b/authentication/migrations/0035_auto_20240803_1454.py new file mode 100644 index 0000000..f12726c --- /dev/null +++ b/authentication/migrations/0035_auto_20240803_1454.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-08-03 14:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0034_auto_20240713_1535'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 53, 59, 484389)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 484389)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 480389)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 480389)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 480389)), + ), + ] diff --git a/authentication/migrations/0036_auto_20240820_1051.py b/authentication/migrations/0036_auto_20240820_1051.py new file mode 100644 index 0000000..3618a2a --- /dev/null +++ b/authentication/migrations/0036_auto_20240820_1051.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-08-20 10:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0035_auto_20240803_1454'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 11, 51, 44, 873391)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 873391)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 868391)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 867392)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 867392)), + ), + ] diff --git a/authentication/migrations/0037_auto_20241031_1409.py b/authentication/migrations/0037_auto_20241031_1409.py new file mode 100644 index 0000000..8e781b9 --- /dev/null +++ b/authentication/migrations/0037_auto_20241031_1409.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-10-31 14:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0036_auto_20240820_1051'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 15, 9, 6, 479600)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 479600)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 476123)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 476123)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 476123)), + ), + ] diff --git a/authentication/migrations/0038_auto_20241109_2158.py b/authentication/migrations/0038_auto_20241109_2158.py new file mode 100644 index 0000000..69964e5 --- /dev/null +++ b/authentication/migrations/0038_auto_20241109_2158.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-11-09 21:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0037_auto_20241031_1409'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 58, 37, 809006)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 809006)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 805501)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 804501)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 804501)), + ), + ] diff --git a/authentication/migrations/0039_auto_20241201_1016.py b/authentication/migrations/0039_auto_20241201_1016.py new file mode 100644 index 0000000..44b5126 --- /dev/null +++ b/authentication/migrations/0039_auto_20241201_1016.py @@ -0,0 +1,183 @@ +# Generated by Django 3.2.13 on 2024-12-01 10: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', '0038_auto_20241109_2158'), + ] + + 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)), + ('images', 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.AddField( + model_name='city', + name='product_price', + field=models.FloatField(default=0), + ), + 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='address', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='bankcard', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='city', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='cityunit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='externaltransaction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='geopoint', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='log', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='multirole', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='permissionlevel', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='province', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='sendingmessagemethod', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='systemaddress', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='systemuserprofile', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='tenant', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 11, 16, 19, 43259)), + ), + migrations.AlterField( + model_name='usermessage', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 16, 19, 43259)), + ), + migrations.AlterField( + model_name='usermessagesend', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='usermessagetype', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 16, 19, 40251)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 16, 19, 40251)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 16, 19, 40251)), + ), + 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/0040_auto_20241208_1514.py b/authentication/migrations/0040_auto_20241208_1514.py new file mode 100644 index 0000000..f2e940d --- /dev/null +++ b/authentication/migrations/0040_auto_20241208_1514.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-08 15:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0039_auto_20241201_1016'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 16, 14, 18, 621700)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 621700)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 619697)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 617695)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 617695)), + ), + ] diff --git a/authentication/migrations/0041_auto_20241227_1500.py b/authentication/migrations/0041_auto_20241227_1500.py new file mode 100644 index 0000000..ade6200 --- /dev/null +++ b/authentication/migrations/0041_auto_20241227_1500.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-27 15:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0040_auto_20241208_1514'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 59, 54, 138496)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 14, 59, 54, 138496)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 14, 59, 54, 135497)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 14, 59, 54, 135497)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 14, 59, 54, 135497)), + ), + ] diff --git a/authentication/migrations/0042_auto_20241227_1519.py b/authentication/migrations/0042_auto_20241227_1519.py new file mode 100644 index 0000000..050ec63 --- /dev/null +++ b/authentication/migrations/0042_auto_20241227_1519.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-27 15:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0041_auto_20241227_1500'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 16, 18, 53, 301217)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 18, 53, 301217)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 18, 53, 297173)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 18, 53, 297173)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 18, 53, 297173)), + ), + ] diff --git a/authentication/migrations/0043_auto_20241227_1534.py b/authentication/migrations/0043_auto_20241227_1534.py new file mode 100644 index 0000000..a27a460 --- /dev/null +++ b/authentication/migrations/0043_auto_20241227_1534.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-27 15:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0042_auto_20241227_1519'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 16, 34, 24, 188820)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 34, 24, 188820)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 34, 24, 184820)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 34, 24, 184820)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 27, 15, 34, 24, 184820)), + ), + ] diff --git a/authentication/migrations/0044_auto_20241228_1054.py b/authentication/migrations/0044_auto_20241228_1054.py new file mode 100644 index 0000000..6c4da58 --- /dev/null +++ b/authentication/migrations/0044_auto_20241228_1054.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-28 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0043_auto_20241227_1534'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 11, 54, 29, 553329)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 10, 54, 29, 553329)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 10, 54, 29, 553329)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 10, 54, 29, 553329)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 10, 54, 29, 553329)), + ), + ] diff --git a/authentication/migrations/0045_auto_20250112_1928.py b/authentication/migrations/0045_auto_20250112_1928.py new file mode 100644 index 0000000..7fe4012 --- /dev/null +++ b/authentication/migrations/0045_auto_20250112_1928.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-12 19:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0044_auto_20241228_1054'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 20, 28, 27, 233996)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 233996)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 229988)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 229988)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 229988)), + ), + ] diff --git a/authentication/migrations/0046_auto_20250118_1751.py b/authentication/migrations/0046_auto_20250118_1751.py new file mode 100644 index 0000000..8a1a5f9 --- /dev/null +++ b/authentication/migrations/0046_auto_20250118_1751.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-18 17:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0045_auto_20250112_1928'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 18, 51, 37, 10372)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 17, 51, 37, 10372)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 17, 51, 37, 7378)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 17, 51, 37, 7378)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 17, 51, 37, 7378)), + ), + ] diff --git a/authentication/migrations/0047_auto_20250121_0922.py b/authentication/migrations/0047_auto_20250121_0922.py new file mode 100644 index 0000000..0147c6a --- /dev/null +++ b/authentication/migrations/0047_auto_20250121_0922.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-01-21 09:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0046_auto_20250118_1751'), + ] + + 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, 10, 22, 49, 487376)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 9, 22, 49, 487376)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 9, 22, 49, 487376)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 9, 22, 49, 487376)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 9, 22, 49, 487376)), + ), + ] diff --git a/authentication/migrations/0048_auto_20250201_1221.py b/authentication/migrations/0048_auto_20250201_1221.py new file mode 100644 index 0000000..60559cd --- /dev/null +++ b/authentication/migrations/0048_auto_20250201_1221.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-02-01 12:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0047_auto_20250121_0922'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 13, 21, 20, 928031)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 12, 21, 20, 928031)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 12, 21, 20, 925031)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 12, 21, 20, 925031)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 12, 21, 20, 925031)), + ), + ] diff --git a/authentication/migrations/0049_auto_20250303_2034.py b/authentication/migrations/0049_auto_20250303_2034.py new file mode 100644 index 0000000..0ea6785 --- /dev/null +++ b/authentication/migrations/0049_auto_20250303_2034.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-03 20:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0048_auto_20250201_1221'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 21, 34, 11, 354096)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 354096)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 351096)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 351096)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 351096)), + ), + ] diff --git a/authentication/migrations/0050_auto_20250303_2036.py b/authentication/migrations/0050_auto_20250303_2036.py new file mode 100644 index 0000000..cb6df06 --- /dev/null +++ b/authentication/migrations/0050_auto_20250303_2036.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-03 20:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0049_auto_20250303_2034'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 21, 35, 52, 633610)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 633610)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 630615)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 630615)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 630615)), + ), + ] diff --git a/authentication/migrations/0051_auto_20250306_1213.py b/authentication/migrations/0051_auto_20250306_1213.py new file mode 100644 index 0000000..04fab0f --- /dev/null +++ b/authentication/migrations/0051_auto_20250306_1213.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-06 12:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0050_auto_20250303_2036'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 13, 12, 51, 938634)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 12, 12, 51, 938634)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 12, 12, 51, 935071)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 12, 12, 51, 934085)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 12, 12, 51, 934085)), + ), + ] diff --git a/authentication/migrations/0052_auto_20250527_1054.py b/authentication/migrations/0052_auto_20250527_1054.py new file mode 100644 index 0000000..f9ed5ca --- /dev/null +++ b/authentication/migrations/0052_auto_20250527_1054.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-27 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0051_auto_20250306_1213'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 11, 54, 19, 292383)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 292383)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 289162)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 289162)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 289162)), + ), + ] diff --git a/authentication/migrations/0053_auto_20250527_1202.py b/authentication/migrations/0053_auto_20250527_1202.py new file mode 100644 index 0000000..e01411b --- /dev/null +++ b/authentication/migrations/0053_auto_20250527_1202.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-27 12:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0052_auto_20250527_1054'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 13, 2, 13, 462321)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 2, 13, 462321)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 2, 13, 462321)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 2, 13, 462321)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 2, 13, 462321)), + ), + ] diff --git a/authentication/migrations/0054_auto_20250528_1439.py b/authentication/migrations/0054_auto_20250528_1439.py new file mode 100644 index 0000000..af2bb39 --- /dev/null +++ b/authentication/migrations/0054_auto_20250528_1439.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-28 14:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0053_auto_20250527_1202'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 37, 38, 358727)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 358727)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 37, 831944)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 37, 831944)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 37, 831944)), + ), + ] diff --git a/authentication/migrations/0055_auto_20250601_1035.py b/authentication/migrations/0055_auto_20250601_1035.py new file mode 100644 index 0000000..9354bda --- /dev/null +++ b/authentication/migrations/0055_auto_20250601_1035.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-06-01 10:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0054_auto_20250528_1439'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 11, 35, 36, 556531)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 556531)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 556531)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 556531)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 556531)), + ), + ] diff --git a/authentication/migrations/0056_auto_20250901_1650.py b/authentication/migrations/0056_auto_20250901_1650.py new file mode 100644 index 0000000..12880e1 --- /dev/null +++ b/authentication/migrations/0056_auto_20250901_1650.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-09-01 16:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0055_auto_20250601_1035'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 17, 50, 12, 908876)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 908876)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 894937)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 894937)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 894937)), + ), + ] diff --git a/authentication/migrations/0057_auto_20250920_1316.py b/authentication/migrations/0057_auto_20250920_1316.py new file mode 100644 index 0000000..5639c88 --- /dev/null +++ b/authentication/migrations/0057_auto_20250920_1316.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-09-20 13:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0056_auto_20250901_1650'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 14, 16, 45, 265068)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 265068)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 261975)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 261975)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 261975)), + ), + ] diff --git a/authentication/migrations/0058_auto_20251104_2046.py b/authentication/migrations/0058_auto_20251104_2046.py new file mode 100644 index 0000000..50e3b22 --- /dev/null +++ b/authentication/migrations/0058_auto_20251104_2046.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.13 on 2025-11-04 20:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0057_auto_20250920_1316'), + ] + + 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, 21, 46, 6, 33917)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 20, 46, 6, 33917)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 20, 46, 6, 28911)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 20, 46, 6, 28911)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 20, 46, 6, 28911)), + ), + ] diff --git a/authentication/migrations/0059_auto_20251208_1019.py b/authentication/migrations/0059_auto_20251208_1019.py new file mode 100644 index 0000000..755f851 --- /dev/null +++ b/authentication/migrations/0059_auto_20251208_1019.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-12-08 10:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0058_auto_20251104_2046'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 11, 16, 49, 224741)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 49, 224741)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 49, 220673)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 49, 220673)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 49, 220673)), + ), + ] diff --git a/authentication/migrations/0060_auto_20251213_1627.py b/authentication/migrations/0060_auto_20251213_1627.py new file mode 100644 index 0000000..1def29a --- /dev/null +++ b/authentication/migrations/0060_auto_20251213_1627.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2025-12-13 16:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0059_auto_20251208_1019'), + ] + + 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, 27, 37, 298878)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 298878)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 294668)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 294668)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 294668)), + ), + ] diff --git a/authentication/migrations/0061_auto_20251214_2351.py b/authentication/migrations/0061_auto_20251214_2351.py new file mode 100644 index 0000000..08a00ef --- /dev/null +++ b/authentication/migrations/0061_auto_20251214_2351.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-12-14 23:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0060_auto_20251213_1627'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 0, 51, 25, 812615)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 812636)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 809487)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 809419)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 809436)), + ), + ] diff --git a/authentication/migrations/0062_auto_20251217_1642.py b/authentication/migrations/0062_auto_20251217_1642.py new file mode 100644 index 0000000..495e7e7 --- /dev/null +++ b/authentication/migrations/0062_auto_20251217_1642.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-12-17 16:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0061_auto_20251214_2351'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 17, 42, 16, 85358)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 85358)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 81784)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 81784)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 81784)), + ), + ] 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..2fae02b --- /dev/null +++ b/authentication/register.py @@ -0,0 +1,4444 @@ +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 = [] + for bar in province_kill_request: + try: + order_code = bar.province_request.poultry_request.order_code + quantity = to_locale_str(int(bar.quantity)) + kill_request = getattr(bar.province_request, 'kill_request', None) + recive_date = getattr(kill_request, 'recive_date', None) + date_str = shamsi_date(recive_date) if recive_date else '' + info = 'کد سفارش:{0} - وزن:{1} کیلوگرم - تاریخ تخصیص:{2}'.format( + order_code, + quantity, + date_str + ) + bars_info.append(info) + except Exception: + continue + 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 = [] + for bar in province_kill_request: + try: + order_code = bar.province_request.poultry_request.order_code + quantity = to_locale_str(int(bar.quantity)) + kill_request = getattr(bar.province_request, 'kill_request', None) + recive_date = getattr(kill_request, 'recive_date', None) + date_str = shamsi_date(recive_date) if recive_date else '' + info = 'کد سفارش:{0} - وزن:{1} کیلوگرم - تاریخ تخصیص:{2}'.format( + order_code, + quantity, + date_str + ) + bars_info.append(info) + except Exception: + continue + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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) + 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..298583e --- /dev/null +++ b/authentication/sahandsms/sms.py @@ -0,0 +1,588 @@ +# توابع مورد نیاز برای اتصال به ای پی آی سهند اس ام اس +from panel.helper import check_mobile_number +from ..models import SystemUserProfile +import requests +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='hamedan' +OUT_SMS_PASS='hamedan12345' +kill_house_price=15000 + +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..ea1f4e1 --- /dev/null +++ b/authentication/serializers.py @@ -0,0 +1,104 @@ +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..4a0fadf --- /dev/null +++ b/authentication/sms_management.py @@ -0,0 +1,3245 @@ +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, check_kill_house_remain_limitation_weight +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' \ + 'کد احراز: {5}\n' \ + 'سامانه رصدیار'.format(seller, date, buyer, 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) + + +def send_block_panel_sms_for_kill_house(kill_house_list, date): + if base_url_for_sms_report == 'ha': + + date_shamsi = shamsi_date(date) if date else shamsi_date(datetime.now().date()) + + for kill_house in kill_house_list: + kill_house_name = kill_house.name if hasattr(kill_house, 'name') else str(kill_house) + mobile = kill_house.kill_house_operator.user.mobile + + if not mobile: + continue + + message = f'کاربر گرامی\n' \ + f'\n' \ + f'کشتارگاه {kill_house_name}\n' \ + f'\n' \ + f'باتوجه به عدم توزیع گوشت مرغ و مانده انبار شما در تاریخ {date_shamsi} پنل خرید مرغ زنده شما مسدود میباشد.جهت پیگری و باز شدن پنل خود به مدیریت بازرسی و نظارت بر محصولات کشاورزی استان خود مراجعه فرمائید.\n' \ + f'\n' \ + f'(سامانه رصدیار)' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={mobile}&message={message}") + req1 = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to=09011110919&message={message}") + req2 = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to=09185914818&message={message}") + req3 = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to=09188198829&message={message}") + req4 = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to=09187065640&message={message}") + + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + + +def send_sms_for_blocked_kill_houses(target_date=None): + if target_date is None: + target_date = datetime.now().date() + + date_shamsi = shamsi_date(target_date) + + kill_houses = KillHouse.objects.filter( + trash=False, + out_province=False + ).select_related('kill_house_operator__user') + + blocked_kill_houses = [] + + for kill_house in kill_houses: + ware_house_lock = False + + 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 + + if ware_house_lock: + blocked_kill_houses.append(kill_house) + + if blocked_kill_houses: + send_block_panel_sms_for_kill_house(blocked_kill_houses, target_date) + + return len(blocked_kill_houses) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def send_sms_for_blocked_kill_houses_endpoint(request): + target_date = None + if 'date' in request.GET: + try: + from datetime import datetime as dt + target_date = dt.strptime(request.GET['date'], '%Y-%m-%d').date() + except ValueError: + return HttpResponse('فرمت تاریخ نامعتبر است. فرمت صحیح: YYYY-MM-DD', status=status.HTTP_400_BAD_REQUEST) + + count = send_sms_for_blocked_kill_houses(target_date) + return HttpResponse(f'پیامک برای {count} کشتارگاه مسدود شده ارسال شد.', status=status.HTTP_200_OK) + + +def send_sms_for_blocked_kill_houses_endpoint_cron(): + target_date = None + send_sms_for_blocked_kill_houses(target_date) + + +def send_kill_house_debt_report_pdf_sms(): + if base_url_for_sms_report == 'ha': + """ + ارسال پیامک با لینک گزارش بدهی کشتارگاه و مباشرین به 4 شماره خاص + این گزارش شامل اطلاعات کشتارگاه‌ها و مباشرین با مانده انبار است + """ + date_shamsi = shamsi_date(datetime.now().date()) + + # ساخت لینک PDF + pdf_url = f'https://{base_url_for_sms_report}backend.rasadyar.com/kdp/' + + message = f'گزارش مانده انبار گوشت مرغ کشتارگاه و مباشر' \ + f'\n' \ + f'مورخ: {date_shamsi}' \ + f'\n' \ + f'لینک دریافت گزارش:' \ + f'\n' \ + f'{pdf_url}' \ + f'\n' \ + f'(سامانه رصدیار)' + + # لیست شماره‌های دریافت کننده + recipient_numbers = [ + '09011110919', + '09185914818', + '09188198829', + '09187065640' + ] + + # ارسال پیامک به هر شماره + for mobile in recipient_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={mobile}&message={message}") + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + + +def send_kill_house_debt_report_pdf_sms_manual(request): + if base_url_for_sms_report == 'ha': + """ + ارسال پیامک با لینک گزارش بدهی کشتارگاه و مباشرین به 4 شماره خاص + این گزارش شامل اطلاعات کشتارگاه‌ها و مباشرین با مانده انبار است + """ + date_shamsi = shamsi_date(datetime.now().date()) + + # ساخت لینک PDF + pdf_url = f'https://{base_url_for_sms_report}backend.rasadyar.com/kdp/' + + message = f'گزارش مانده انبار گوشت مرغ کشتارگاه و مباشر' \ + f'\n' \ + f'مورخ: {date_shamsi}' \ + f'\n' \ + f'لینک دریافت گزارش:' \ + f'\n' \ + f'{pdf_url}' \ + f'\n' \ + f'(سامانه رصدیار)' + + # لیست شماره‌های دریافت کننده + recipient_numbers = [ + '09011110919', + '09185914818', + '09188198829', + '09187065640' + ] + + # ارسال پیامک به هر شماره + for mobile in recipient_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={mobile}&message={message}") + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + return HttpResponse('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..07c6627 --- /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"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + if base_url_for_sms_report == 'ha': + 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"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + if base_url_for_sms_report == 'ha': + 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"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + if base_url_for_sms_report == 'ha': + 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"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + if base_url_for_sms_report == 'ha': + 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..965062d --- /dev/null +++ b/cancel_bar_and_provice_request.py @@ -0,0 +1,15 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() + +from panel.KillHouse.views import cancel_bar_and_province_request_cron +from panel.ReportingPanel.views import archive_kill_house_remain_limitation_weight_cron +from panel.KillHouse.helpers import create_kill_house_free_bar_cron + +cancel_bar_and_province_request_cron() +archive_kill_house_remain_limitation_weight_cron() +create_kill_house_free_bar_cron() diff --git a/cancel_out_provice.py b/cancel_out_provice.py new file mode 100644 index 0000000..4063251 --- /dev/null +++ b/cancel_out_provice.py @@ -0,0 +1,16 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() + +from authentication.register import canceled_out_province_request +from panel.ReportingPanel.views import delete_steward_allocation_cron, delete_sale_bar + +canceled_out_province_request() + +delete_steward_allocation_cron() +delete_sale_bar() + diff --git a/cron.py b/cron.py new file mode 100644 index 0000000..3dfc19b --- /dev/null +++ b/cron.py @@ -0,0 +1,24 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() + +from authentication.register import update_chicken_age_from_login, fix_duplicate_order_code_new_cron, \ + add_free_bar_to_warehouse_cron, add_free_bar_to_warehouse_automatic_type_cron +from panel.ReportingPanel.views import remove_access_token, cron_update_poultry_hatching_from_rsi +from ticket.views import closed_unread_ticket_cron +from authentication.sms_management import send_sms_for_blocked_kill_houses_endpoint_cron, \ + send_kill_house_debt_report_pdf_sms + +update_chicken_age_from_login() +remove_access_token() +# cron_update_poultry_hatching_from_rsi() +closed_unread_ticket_cron() +fix_duplicate_order_code_new_cron() +add_free_bar_to_warehouse_cron() +add_free_bar_to_warehouse_automatic_type_cron() +send_sms_for_blocked_kill_houses_endpoint_cron() +send_kill_house_debt_report_pdf_sms() \ No newline at end of file diff --git a/cron_bad_transactions.py b/cron_bad_transactions.py new file mode 100644 index 0000000..05cd843 --- /dev/null +++ b/cron_bad_transactions.py @@ -0,0 +1,9 @@ +import os +import django + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") +django.setup() + +from panel.ProvinceOperator.helpers import calculate_bad_transactions + +calculate_bad_transactions() diff --git a/cron_gid.py b/cron_gid.py new file mode 100644 index 0000000..1bb08dc --- /dev/null +++ b/cron_gid.py @@ -0,0 +1,20 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") +django.setup() +from panel.ReportingPanel.views import cron_find_gid_code, get_gid_out_province_cron_job, hatching_unknown_cron +from panel.KillHouse.helpers import create_kill_house_free_bar_cron +from authentication.register import add_to_warehouse, fix_duplicate_order_code_cron +from bot_eata import daily_report_for_each_vet_farm_cron +from panel.excel_processing import test_all_excel_functions_cron + +cron_find_gid_code() +create_kill_house_free_bar_cron() +add_to_warehouse() +get_gid_out_province_cron_job() +fix_duplicate_order_code_cron() +daily_report_for_each_vet_farm_cron() +test_all_excel_functions_cron() +hatching_unknown_cron() diff --git a/cron_out_province_request.py b/cron_out_province_request.py new file mode 100644 index 0000000..da2dcb9 --- /dev/null +++ b/cron_out_province_request.py @@ -0,0 +1,19 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() + +from authentication.register import canceled_out_province_request +from bot_eata import daily_cron_job_transaction_for_eata +from panel.ReportingPanel.views import send_credit_sahandsms_sms +from bot_eata import send_all_bar_to_eitaa_cron +from authentication.sms_management import send_daily_slaughter_statistics_sms + +# canceled_out_province_request() +daily_cron_job_transaction_for_eata() +send_credit_sahandsms_sms() +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..c1b2f45 --- /dev/null +++ b/cron_report.py @@ -0,0 +1,12 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() +from authentication.sms_management import reporting_sms +from panel.ReportingPanel.views import send_sms_for_poultry_from_age_notification + +reporting_sms() +send_sms_for_poultry_from_age_notification() diff --git a/cron_return_archive.py b/cron_return_archive.py new file mode 100644 index 0000000..01aa1e6 --- /dev/null +++ b/cron_return_archive.py @@ -0,0 +1,11 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.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_sms.py b/cron_sms.py new file mode 100644 index 0000000..856bf7f --- /dev/null +++ b/cron_sms.py @@ -0,0 +1,17 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.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/cron_then_am.py b/cron_then_am.py new file mode 100644 index 0000000..4ece4d1 --- /dev/null +++ b/cron_then_am.py @@ -0,0 +1,11 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() +from authentication.sms_management import send_daily_distribution_report_sms + + +send_daily_distribution_report_sms() \ No newline at end of file diff --git a/delete_kill_request_cron.py b/delete_kill_request_cron.py new file mode 100644 index 0000000..887b3d0 --- /dev/null +++ b/delete_kill_request_cron.py @@ -0,0 +1,11 @@ +import os + +import django + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.settings") + +django.setup() + +from panel.ReportingPanel.views import delete_kill_req_cron + +delete_kill_req_cron() diff --git a/deposit_id.py b/deposit_id.py new file mode 100644 index 0000000..ab95d22 --- /dev/null +++ b/deposit_id.py @@ -0,0 +1,26 @@ +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 = False +new_out_selling_count_wage_date = '2025-08-07' +before_out_buying_count_wage_amount = 1000 +extra_company_amount = 200 +province_id = '30' +market_code_state = True + diff --git a/deposit_percent.py b/deposit_percent.py new file mode 100644 index 0000000..f84642c --- /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 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..e7d7181 --- /dev/null +++ b/every_12_hours.py @@ -0,0 +1,15 @@ +import os +import django + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "HaChickenStore.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..5d7289c --- /dev/null +++ b/general_urls.py @@ -0,0 +1,11 @@ +# کلاینت سیکرت برای سیستم ورود و ثبت نام بر اساس توکن +CLIENT_SECRET = "EcGNX0TpTBGKAorLHkDv8fASIFSyqusIDdbWh0HeMyOBIRo8ypo5EwXnZIKCDglXWgAHs69wgsXXKN3Mz7CD5apWPficbteO7mD1fnTZj7w66Lk2Qzh3WeF8Ry1QuEKE" +# کلاینت ای دی برای سیستم ورود و ثبت نام بر اساس توکن +CLIENT_ID = "MdGxzQuaIvYap1EbYhgg7Y6x7rzptz7sXU3pB6FZ" + +BASE_URL = "https://habackend.rasadyar.com/api/" + +base_pos_id='ha' +base_user_gate_way_id='h' +base_url_sms='ha' +base_url_for_sms_report='ha' diff --git a/helper_eata.py b/helper_eata.py new file mode 100644 index 0000000..986ceef --- /dev/null +++ b/helper_eata.py @@ -0,0 +1,3 @@ +token = 'bot291669:9298e675-8b3c-4b8f-a69d-5c89a3f0bdde' +chat_id = '9763210' +chat_id_mali = '10339263' diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..a68effd --- /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', 'HaChickenStore.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..ed06fc2 --- /dev/null +++ b/notification/migrations/0001_initial.py @@ -0,0 +1,115 @@ +# Generated by Django 3.2.13 on 2022-12-04 13:13 + +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), + ('authentication', '0001_initial'), + ] + + 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_20250303_2034.py b/notification/migrations/0002_auto_20250303_2034.py new file mode 100644 index 0000000..ac70962 --- /dev/null +++ b/notification/migrations/0002_auto_20250303_2034.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-03 20:34 + +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..d8bf229 --- /dev/null +++ b/notification/migrations/0003_dashboardnotification.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2025-06-15 16:35 + +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_20250303_2034'), + ] + + 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='dashboard_notification', to='auth.Group')), + ], + options={ + 'abstract': False, + }, + ), + ] 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..9c9898d --- /dev/null +++ b/panel/KillHouse/helpers.py @@ -0,0 +1,2134 @@ +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) +# } +# response = requests.post('https://rsibackend.rasadyar.com/app/get_bar_info/', data=kill_house_list) +# try: +# bars = response.json() +# except ValueError: +# return +# if not isinstance(bars, list): +# return +# for bar in bars: +# try: +# if not isinstance(bar, dict): +# continue +# des_part_id_code = bar.get('DesPartIdCode') +# if not des_part_id_code: +# continue +# kill_house = KillHouse.objects.filter(trash=False, unique_identifier=des_part_id_code).first() +# if not kill_house: +# continue +# if KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=bar.get('TrackingCode')).exists(): +# continue +# product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() +# formatted_str = str(bar.get('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.get('hatching', {}).get('poultry', {}).get('UnitName') +# kill_house_free_bar_info.poultry_mobile = bar.get('hatching', {}).get('poultry', {}).get('Mobile') +# kill_house_free_bar_info.province = bar.get('hatching', {}).get('poultry', {}).get('Province') +# kill_house_free_bar_info.city = bar.get('hatching', {}).get('poultry', {}).get('City') +# kill_house_free_bar_info.bar_clearance_code = bar.get('TrackingCode') +# kill_house_free_bar_info.quantity = bar.get('GoodAmount') +# kill_house_free_bar_info.live_weight = int(int(bar.get('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 and wage_type.status is 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 is 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() +# except Exception: +# continue +# return HttpResponse('ok') + + +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) + } + response = requests.post('https://rsibackend.rasadyar.com/app/get_bar_info/', data=kill_house_list) + try: + bars = response.json() + except ValueError: + return + if not isinstance(bars, list): + return + for bar in bars: + try: + if not isinstance(bar, dict): + continue + des_part_id_code = bar.get('jihadi_destination') + if not des_part_id_code: + continue + kill_house = KillHouse.objects.filter(trash=False, unique_identifier=des_part_id_code).first() + if not kill_house: + continue + if KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=bar.get('tracking')).exists(): + continue + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + formatted_str = str(bar.get('date')).replace('T', ' ').replace('Z', '') + date = datetime.datetime.strptime(formatted_str, '%Y-%m-%d').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.get('hatching', {}).get('poultry', {}).get('UnitName') + kill_house_free_bar_info.poultry_mobile = bar.get('hatching', {}).get('poultry', {}).get('Mobile') + kill_house_free_bar_info.province = bar.get('hatching', {}).get('poultry', {}).get('Province') + kill_house_free_bar_info.city = bar.get('hatching', {}).get('poultry', {}).get('City') + kill_house_free_bar_info.bar_clearance_code = bar.get('tracking') + kill_house_free_bar_info.quantity = bar.get('quantity') + kill_house_free_bar_info.live_weight = int(int(bar.get('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 and wage_type.status is 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 is 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() + except Exception: + continue + 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) + } + response = requests.post('https://rsibackend.rasadyar.com/app/get_bar_info/', data=kill_house_list) + try: + bars = response.json() + except ValueError: + return + if not isinstance(bars, list): + return + for bar in bars: + try: + if not isinstance(bar, dict): + continue + des_part_id_code = bar.get('jihadi_destination') + if not des_part_id_code: + continue + kill_house = KillHouse.objects.filter(trash=False, unique_identifier=des_part_id_code).first() + if not kill_house: + continue + if KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=bar.get('tracking')).exists(): + continue + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + formatted_str = str(bar.get('date')).replace('T', ' ').replace('Z', '') + date = datetime.datetime.strptime(formatted_str, '%Y-%m-%d').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.get('hatching', {}).get('poultry', {}).get('UnitName') + kill_house_free_bar_info.poultry_mobile = bar.get('hatching', {}).get('poultry', {}).get('Mobile') + kill_house_free_bar_info.province = bar.get('hatching', {}).get('poultry', {}).get('Province') + kill_house_free_bar_info.city = bar.get('hatching', {}).get('poultry', {}).get('City') + kill_house_free_bar_info.bar_clearance_code = bar.get('tracking') + kill_house_free_bar_info.quantity = bar.get('quantity') + kill_house_free_bar_info.live_weight = int(int(bar.get('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 and wage_type.status is 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 is 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() + except Exception: + continue + + +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..a8bca44 --- /dev/null +++ b/panel/KillHouse/views.py @@ -0,0 +1,19753 @@ +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: + if not limitation_direct_purchase.allow_buying: + is_in_limitation_range = False + else: + if 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 and \ + free_bar.register_type != 'automatic': + 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 + product = RolesProducts.objects.filter(kill_house=exclusive_killer, trash=False, name='مرغ گرم').first() + free_bar.product = product + if free_bar.exclusive_killer: + free_bar.exclusive_killer = None + else: + free_bar.exclusive_killer = exclusive_killer + free_bar.input_warehouse = exclusive_killer + product = RolesProducts.objects.filter(kill_house=exclusive_killer, trash=False, name='مرغ گرم').first() + free_bar.product = product + 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() + 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(free_bar.product) + 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: + if kill_house_purchase.limitation == True: + + 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..7fb78ef --- /dev/null +++ b/panel/ProvinceOperator/serializers.py @@ -0,0 +1,6381 @@ +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): + lat = serializers.FloatField(source='lot', read_only=True) + lng = serializers.FloatField(read_only=True) + guilds_name = serializers.CharField(source='pos.guild.guilds_name', read_only=True) + + class Meta: + model = POSDeviceSession + fields = ['lat', 'lng', 'guilds_name'] + +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..21d9b09 --- /dev/null +++ b/panel/ProvinceOperator/views.py @@ -0,0 +1,27767 @@ +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 + if allocations_type == 'Steward': + allocations = StewardAllocation.objects.filter(Q(steward__isnull=False)|Q(guilds__isnull=False),**filters) + else: + + 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 + + + if allocations_type == 'Steward': + allocations = StewardAllocation.objects.filter(Q(steward__isnull=False)|Q(guilds__isnull=False),**filters).order_by('-date') + else: + 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, + pos__guild__isnull=False + ).select_related( + 'pos', + 'pos__guild', + 'pos__user' + ).values( + 'lng', 'lot', 'pos__guild__guilds_name', 'key', + 'pos__user__national_code', 'pos__user__national_id' + ).order_by('id') + + result = [ + { + 'key': item['key'], + 'lat': item['lot'], + 'lng': item['lng'], + 'guilds_name': item['pos__guild__guilds_name'], + 'national_code': item['pos__user__national_code'], + 'national_id': item['pos__user__national_id'] + } + for item in pos_devices + ] + + return Response(result, 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.address.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..d75eadc --- /dev/null +++ b/panel/ReportingPanel/helper.py @@ -0,0 +1,179 @@ +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', + +] \ No newline at end of file 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..3732677 --- /dev/null +++ b/panel/ReportingPanel/views.py @@ -0,0 +1,9339 @@ +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: + try: + 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() + if kill.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() + except Exception: + continue + + +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(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def new_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_stewards.user.mobile + buyer = steward_allocation.to_stewards.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} + 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() + 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) + 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', []) + + if not guild_list or len(guild_list) == 0: + return Response({"result": "اطلاعات صنفی یافت نشد با واحد پشتیبانی تماس بگیرید."}, + status=status.HTTP_403_FORBIDDEN) + + 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 = [] + + 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) + + if not active_guilds and inactive_guilds: + 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 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 + + if not guild_info and guild_list: + guild_info = guild_list[0] + + if active_guilds: + api_data['guild'] = active_guilds + elif guild_info: + api_data['guild'] = guild_info + except Exception as e: + if 'active_guilds' in locals() and active_guilds: + api_data['guild'] = active_guilds + elif 'guild_info' in locals() and guild_info: + api_data['guild'] = guild_info + 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() + + 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: + 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: + users_with_valid_guilds = users_with_valid_guilds[:1] + + 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() + + steward_guilds = guilds.filter(steward=True) + guilds_to_keep_active.update(steward_guilds.values_list('id', flat=True)) + + guilds_with_allocation_info = [] + 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: + 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 + }) + + 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) + 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) + + 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([TokenHasReadWriteScope]) +def get_guilds_for_update_or_create_new(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} + 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() + 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) + 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', []) + + if not guild_list or len(guild_list) == 0: + return Response({"result": "اطلاعات صنفی یافت نشد با واحد پشتیبانی تماس بگیرید."}, + status=status.HTTP_403_FORBIDDEN) + + 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 = [] + + 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) + + if not active_guilds and inactive_guilds: + 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 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 + + if not guild_info and guild_list: + guild_info = guild_list[0] + + if active_guilds: + api_data['guild'] = active_guilds + elif guild_info: + api_data['guild'] = guild_info + except Exception as e: + if 'active_guilds' in locals() and active_guilds: + api_data['guild'] = active_guilds + elif 'guild_info' in locals() and guild_info: + api_data['guild'] = guild_info + 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() + + 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: + 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: + users_with_valid_guilds = users_with_valid_guilds[:1] + + 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() + + steward_guilds = guilds.filter(steward=True) + guilds_to_keep_active.update(steward_guilds.values_list('id', flat=True)) + + guilds_with_allocation_info = [] + 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: + 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 + }) + + 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) + 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) + + 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(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fetch_evacuation_details_for_unknown_hatchings(request): + hatchings = ( + PoultryHatching.objects + .filter( + Q(unknown=True) | Q(state='pending', allow_hatching='pending', archive=False), + trash=False, + licence_number__isnull=False, + ) + ) + + licence_numbers = list(hatchings.values_list('licence_number', flat=True).distinct()) + + try: + payload = {"codes": licence_numbers} + external_response = requests.post( + "http://rsibackend.rasadyaar.ir/app/get-evacuation-details-by-request-codes/", + json=payload, + ) + external_response.raise_for_status() + external_data = external_response.json() or {} + except Exception as exc: + return Response( + {"result": f"خطا در ارتباط با سرویس تلفات: {str(exc)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + + created_count = 0 + updated_count = 0 + skipped_no_data = 0 + + report_type_field_map = { + 'تلفات ناشی از بیماری': 'total_disease_losses', + 'معدوم سازی گله': 'total_flock_destruction', + 'تلفات عادی گله': 'total_normal_flock_losses', + 'تلفات ناشی از عوامل قهری و طبیعی': 'total_force_majeure_losses', + 'تلفات ناشی از آتش سوزی': 'total_fire_losses', + } + report_type_fields = list(set(report_type_field_map.values())) + + 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', + ] + + 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 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 + + 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) + + hatching_map = {h.licence_number: h for h in hatchings} + + for code, details in external_data.items(): + hatching = hatching_map.get(code) + if not hatching: + skipped_no_data += 1 + continue + + if not isinstance(details, list) or not details: + skipped_no_data += 1 + continue + + seen_unique_keys = set() + + for detail in 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} + 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 + lookup_kwargs['trash'] = False + + obj, created = EvacuationHatchingDetail.objects.update_or_create( + defaults=defaults, + **lookup_kwargs, + ) + if created: + created_count += 1 + else: + updated_count += 1 + + apply_evacuation_losses(hatching) + hatching.save() + + return Response( + { + "result": "ثبت تلفات برای جوجه‌ریزی‌های unknown انجام شد.", + "created_details": created_count, + "updated_details": updated_count, + "skipped_already_had_details": updated_count, + "skipped_no_data": skipped_no_data, + "processed_hatchings": len(licence_numbers), + }, + 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..9cf0a95 --- /dev/null +++ b/panel/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin + +# Register your models here. +PROJECT_API_KEY = '33374d79-e8ee-4947-b0b4-4a6d31935814' 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..7dab3b3 --- /dev/null +++ b/panel/excel_processing.py @@ -0,0 +1,38247 @@ +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(trash=False, date__date__gte=date1, + date__date__lte=date2).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 + poultries = Poultry.objects.filter(pk__in=filtered_poultry_hatch.values('poultry'), trash=False) + value_header_list = [ + len(poultries), + 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..41dd192 --- /dev/null +++ b/panel/helper.py @@ -0,0 +1,254 @@ +import re + +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 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='09187040838' +GUILD_NUMBER='09187040838' +UNION_SECOND_NUMBER='09187040838' +SUPPORTER_NUMBER='09165597588' +UNION_THIRD_NUMBER='09185027154' +UNION_FOURTH_NUMBER=None +UNION_NUMBER_2='09186266320' +UNION_FIFTH_NUMBER=None +UNION_SIXTH_NUMBER=None + + + +# 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 \ No newline at end of file diff --git a/panel/helper_excel.py b/panel/helper_excel.py new file mode 100644 index 0000000..39cd7df --- /dev/null +++ b/panel/helper_excel.py @@ -0,0 +1,537 @@ +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 \ No newline at end of file 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..96ac619 --- /dev/null +++ b/panel/merge_database.py @@ -0,0 +1,363 @@ +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 + 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 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..dac49a4 --- /dev/null +++ b/panel/migrations/0001_initial.py @@ -0,0 +1,1383 @@ +# Generated by Django 3.2.13 on 2022-12-04 13: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): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('notification', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0001_initial'), + ] + + 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)), + ('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)), + ('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_state', models.CharField(default='pending', max_length=20)), + ('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='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)), + ('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')), + ], + 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)), + ('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)), + ('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)), + ('status', models.CharField(default='inactive', max_length=50)), + ('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)), + ('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)), + ('state', models.CharField(default='pending', max_length=15)), + ('poultry', models.BooleanField(default=False)), + ('city', models.BooleanField(default=False)), + ('province', models.BooleanField(default=False)), + ('importer', models.JSONField(default=dict, 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='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)), + ('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='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)), + ('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)), + ('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)), + ('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='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_capacity', models.IntegerField(null=True)), + ('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)), + ('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)), + ('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)), + ], + options={ + 'abstract': False, + }, + ), + 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)), + ('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(2022, 12, 4, 13, 13, 23, 263792))), + ('last_party_date', models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 13, 23, 263819))), + ('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(2022, 12, 4, 13, 13, 23, 263995))), + ('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='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)), + ('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=20, 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)), + ('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)), + ('quantity', models.BigIntegerField(default=0)), + ('losses', models.BigIntegerField(default=0)), + ('send_date', models.DateTimeField(null=True)), + ('chicken_breed', models.CharField(max_length=20, 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.IntegerField(null=True)), + ('message', models.CharField(max_length=500, null=True)), + ('inspector', models.CharField(max_length=30, null=True)), + ('union', 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)), + ('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)), + ('state', models.CharField(max_length=20, null=True)), + ('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='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)), + ('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_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)), + ('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='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)), + ('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='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)), + ('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)), + ('hall', models.IntegerField(default=0)), + ('vetfarm_losses', models.BigIntegerField(default=0)), + ('state', models.CharField(default='pending', max_length=20)), + ('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='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)), + ('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)), + ('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)), + ('state', models.CharField(max_length=20, 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='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)), + ('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)), + ('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='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.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)), + ('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)), + ('payment_type', models.CharField(max_length=20, null=True)), + ('payment_dead_line', models.DateTimeField(null=True)), + ('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='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='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)), + ('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)), + ('paid_state', models.CharField(default='pending', max_length=20)), + ('kill_house_factor_info', models.CharField(default='pending', max_length=20)), + ('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)), + ('province_check_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_info', to='panel.provincecheckinformation')), + ], + options={ + 'abstract': False, + }, + ), + 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='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)), + ('state', models.CharField(max_length=20, null=True)), + ('message', models.CharField(max_length=500, 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')), + ('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='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)), + ('floor_price', models.FloatField(null=True)), + ('ceiling_price', models.FloatField(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)), + ], + 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)), + ('state', models.CharField(default='pending', max_length=20)), + ('message', models.CharField(max_length=500, 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.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='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(2022, 12, 4, 13, 13, 23, 259954))), + ('province_operator_last_time_check', models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 13, 23, 260027))), + ('kill_house_last_time_check', models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 13, 23, 260071))), + ('assignment_last_time_check', models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 13, 23, 260110))), + ('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.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='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)), + ('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')), + ], + 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.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=25, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('type_car', 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.IntegerField(null=True)), + ('status', models.CharField(default='inactive', max_length=50)), + ('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')), + ], + 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)), + ('state', models.CharField(max_length=20, null=True)), + ('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='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.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='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(2022, 12, 4, 13, 13, 23, 339260))), + ('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='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_share', models.FloatField(null=True)), + ('city_share', models.FloatField(default=0, null=True)), + ('province_share', models.FloatField(default=0, 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_bank', models.JSONField(default=dict, null=True)), + ('central_union_share', models.FloatField(default=0, null=True)), + ('fanava_share', models.FloatField(default=0, null=True)), + ('deposit_allocation_state', models.CharField(default='pending', max_length=20)), + ('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.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.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, + }, + ), + ] diff --git a/panel/migrations/0002_auto_20221204_1315.py b/panel/migrations/0002_auto_20221204_1315.py new file mode 100644 index 0000000..3988586 --- /dev/null +++ b/panel/migrations/0002_auto_20221204_1315.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.13 on 2022-12-04 13:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 915440)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 854346)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 854274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 854330)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 854311)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 857365)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 857178)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 13, 15, 38, 857203)), + ), + ] diff --git a/panel/migrations/0003_auto_20221204_1402.py b/panel/migrations/0003_auto_20221204_1402.py new file mode 100644 index 0000000..e64f25d --- /dev/null +++ b/panel/migrations/0003_auto_20221204_1402.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.13 on 2022-12-04 14:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0002_auto_20221204_1315'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 60327)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 2528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 2456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 2511)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 2492)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 5690)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 5497)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 4, 14, 2, 53, 5521)), + ), + ] diff --git a/panel/migrations/0004_auto_20221211_0954.py b/panel/migrations/0004_auto_20221211_0954.py new file mode 100644 index 0000000..6e9874d --- /dev/null +++ b/panel/migrations/0004_auto_20221211_0954.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2022-12-11 09:54 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0004_auto_20221211_0954'), + ('panel', '0003_auto_20221204_1402'), + ] + + operations = [ + migrations.AddField( + model_name='inspectoroperator', + name='user_bank_info', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_inspector_bank_info', to='authentication.bankcard'), + ), + migrations.AddField( + model_name='killhousedriver', + name='user_bank_info', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='driver_bank_info', to='authentication.bankcard'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 464115)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 404927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 404851)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 404911)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 404891)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 408632)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 408367)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 11, 9, 53, 57, 408418)), + ), + ] diff --git a/panel/migrations/0005_auto_20221212_0953.py b/panel/migrations/0005_auto_20221212_0953.py new file mode 100644 index 0000000..096c6b1 --- /dev/null +++ b/panel/migrations/0005_auto_20221212_0953.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2022-12-12 09:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0004_auto_20221211_0954'), + ] + + operations = [ + migrations.AddField( + model_name='provincefactortokillhouse', + name='shares', + field=models.JSONField(default=dict, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 872682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 800724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 800636)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 800698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 800678)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 804877)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 804675)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 12, 9, 53, 40, 804723)), + ), + ] diff --git a/panel/migrations/0006_auto_20221221_0001.py b/panel/migrations/0006_auto_20221221_0001.py new file mode 100644 index 0000000..ba5a3ba --- /dev/null +++ b/panel/migrations/0006_auto_20221221_0001.py @@ -0,0 +1,186 @@ +# Generated by Django 3.2.13 on 2022-12-21 00: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), + ('authentication', '0005_auto_20221221_0001'), + ('panel', '0005_auto_20221212_0953'), + ] + + operations = [ + migrations.AddField( + model_name='depositallocation', + name='central_union_share_payment', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='central_union_share_payment_info', + field=models.JSONField(default=list, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='city_share_payment', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='city_share_payment_info', + field=models.JSONField(default=list, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='company_share_payment', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='company_share_payment_info', + field=models.JSONField(default=list, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='fanava_share_payment', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='fanava_share_payment_info', + field=models.JSONField(default=list, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='poultry_share_payment', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='poultry_share_payment_info', + field=models.JSONField(default=list, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='province_share_payment', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='province_share_payment_info', + field=models.JSONField(default=list, null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='pay_for', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 724302)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 663490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 663413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 663473)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 663454)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 666380)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 666216)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 0, 1, 33, 666239)), + ), + 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)), + ('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)), + ('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')), + ], + 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)), + ('province_factor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_factor_info_poultry', to='panel.provincefactortokillhouseforpoultry')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='kill_house_factor_poultry', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor_poultry', to='panel.killhousefactortopoultry'), + ), + 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'), + ), + ] diff --git a/panel/migrations/0007_auto_20221221_0827.py b/panel/migrations/0007_auto_20221221_0827.py new file mode 100644 index 0000000..4ac13f8 --- /dev/null +++ b/panel/migrations/0007_auto_20221221_0827.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.13 on 2022-12-21 08:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0006_auto_20221221_0001'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 425511)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 369230)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 369159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 369214)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 369195)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 372890)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 372428)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 21, 8, 27, 45, 372472)), + ), + ] diff --git a/panel/migrations/0008_auto_20221224_2319.py b/panel/migrations/0008_auto_20221224_2319.py new file mode 100644 index 0000000..91dcfda --- /dev/null +++ b/panel/migrations/0008_auto_20221224_2319.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2022-12-24 23:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0007_auto_20221221_0827'), + ] + + operations = [ + migrations.AddField( + model_name='provincefactortokillhouse', + name='sum_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 541998)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 450913)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 450785)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 450877)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 450839)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 454519)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 454325)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 19, 27, 454349)), + ), + ] diff --git a/panel/migrations/0009_auto_20221224_2325.py b/panel/migrations/0009_auto_20221224_2325.py new file mode 100644 index 0000000..b70a41e --- /dev/null +++ b/panel/migrations/0009_auto_20221224_2325.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2022-12-24 23:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0008_auto_20221224_2319'), + ] + + operations = [ + migrations.AddField( + model_name='provincefactortokillhouseforpoultry', + name='sum_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 178483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 119126)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 119054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 119110)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 119091)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 122385)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 122210)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 24, 23, 25, 21, 122233)), + ), + ] diff --git a/panel/migrations/0010_auto_20221231_1052.py b/panel/migrations/0010_auto_20221231_1052.py new file mode 100644 index 0000000..5813f85 --- /dev/null +++ b/panel/migrations/0010_auto_20221231_1052.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2022-12-31 10:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0009_auto_20221224_2325'), + ] + + operations = [ + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='province_accept', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='kill_house_list', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 407060)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 344862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 344777)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 344846)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 344826)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 347771)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 347602)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2022, 12, 31, 10, 52, 2, 347628)), + ), + ] diff --git a/panel/migrations/0011_auto_20230108_2316.py b/panel/migrations/0011_auto_20230108_2316.py new file mode 100644 index 0000000..be42c67 --- /dev/null +++ b/panel/migrations/0011_auto_20230108_2316.py @@ -0,0 +1,120 @@ +# Generated by Django 3.2.13 on 2023-01-08 23: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', '0010_auto_20221231_1052'), + ] + + operations = [ + migrations.AddField( + model_name='killhouseassignmentinformation', + name='protest_time', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 562600)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 504911)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 504821)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 504893)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 504871)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 507811)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 507642)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 8, 23, 16, 23, 507664)), + ), + 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='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)), + ('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='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, + }, + ), + ] diff --git a/panel/migrations/0012_auto_20230130_1648.py b/panel/migrations/0012_auto_20230130_1648.py new file mode 100644 index 0000000..afe3e20 --- /dev/null +++ b/panel/migrations/0012_auto_20230130_1648.py @@ -0,0 +1,252 @@ +# Generated by Django 3.2.13 on 2023-01-30 16:48 + +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_20230108_2316'), + ] + + operations = [ + 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.IntegerField(null=True)), + ('transaction_type', models.CharField(max_length=20, null=True)), + ('payment_code', models.BigIntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('make_location_state', models.CharField(max_length=20, null=True)), + ('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.AddField( + model_name='cityoperator', + name='unit_name', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='real_quantity', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='awaiting_payment', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='city_operator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_city_operator', to='panel.cityoperator'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 656745)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 585260)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 585181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 585243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 585222)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 588818)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 588582)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 1, 30, 16, 48, 16, 588609)), + ), + 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)), + ('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='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='Iwallet', + 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.FloatField(null=True)), + ('type', models.CharField(max_length=50, null=True)), + ('description', models.TextField(null=True)), + ('image', models.JSONField(null=True)), + ('payment_code', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='iwallet_createdby', to=settings.AUTH_USER_MODEL)), + ('itransaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='iwallet_itransaction', to='panel.itransaction')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='iwallet_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + 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.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)), + ('cost', models.FloatField(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='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)), + ], + 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.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.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.AddField( + model_name='killhousedriver', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='driver_wallet', to='panel.wallet'), + ), + migrations.AddField( + model_name='killhouseoperator', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_wallet', to='panel.wallet'), + ), + 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.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.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'), + ), + ] diff --git a/panel/migrations/0013_auto_20230212_1532.py b/panel/migrations/0013_auto_20230212_1532.py new file mode 100644 index 0000000..9dd1950 --- /dev/null +++ b/panel/migrations/0013_auto_20230212_1532.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-02-12 15:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0012_auto_20230130_1648'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='assignment', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 909950)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 853867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 853799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 853851)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 853832)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 856683)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 856543)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 2, 12, 15, 32, 49, 856566)), + ), + ] diff --git a/panel/migrations/0014_auto_20230603_2204.py b/panel/migrations/0014_auto_20230603_2204.py new file mode 100644 index 0000000..6aca153 --- /dev/null +++ b/panel/migrations/0014_auto_20230603_2204.py @@ -0,0 +1,978 @@ +# Generated by Django 3.2.13 on 2023-06-03 22:04 + +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', '0006_auto_20230603_2204'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0013_auto_20230212_1532'), + ] + + operations = [ + 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)), + ('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, + }, + ), + 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='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)), + ], + 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)), + ], + options={ + 'abstract': False, + }, + ), + 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='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)), + ('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.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)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseallowvet_createdby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + 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)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseassignmentimages_createdby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + 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)), + ], + 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)), + ('percent', models.FloatField(default=0)), + ('quantity', models.BigIntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepercentage_createdby', to=settings.AUTH_USER_MODEL)), + ], + 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)), + ('state', models.CharField(default='pending', max_length=20)), + ('amount', models.FloatField(default=0)), + ('minimum_amount', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequestfactor_createdby', 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)), + ('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)), + ('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.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)), + ('city', 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='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)), + ], + 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)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregistercar_createdby', to=settings.AUTH_USER_MODEL)), + ], + 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)), + ], + 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)), + ('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='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='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)), + ('input_quantity', models.BigIntegerField(default=0)), + ('kill_requests_quantity', models.BigIntegerField(default=0)), + ('date', models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 234019))), + ('age_up_45', models.BigIntegerField(default=0, 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='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)), + ('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)), + ], + 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)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('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')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='cityoperator', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='financialdocument', + name='payment_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='financialdocument', + name='type', + field=models.CharField(max_length=30, null=True), + ), + migrations.AddField( + model_name='financialdocument', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financial_wallet', to='panel.wallet'), + ), + migrations.AddField( + model_name='inspectoroperator', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='itransaction', + name='file_id', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='killer', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='exploited_carcass', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='unusual_casualties', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='weight_withs_losses', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='role', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhousecomplaint', + name='registrar', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='registrar', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='first_payment', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouseoperator', + name='killer', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouseoperator', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='clearance_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='registrar_clearance_code', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='role', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='traffic_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='Index_weight', + field=models.FloatField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='chicken_breed', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='debt', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='debt_amount', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='factor_amount', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='factor_deposit', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='first_average_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='message', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='old_chicken_breed', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='payment_info', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='province_quantity', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='province_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AddField( + model_name='killrequest', + name='registrar', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='second_average_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='slaughter_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='slaughter_kill_req', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killrequest', + name='sms_payment', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultry', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='archive', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryhatching', + name='breed', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='message', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='registrar', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='buyer', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='clearance_code', + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='first_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='general_order_code', + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='out', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='previous_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='registrar', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='vet', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='pricing', + name='lock', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='pricing', + name='operator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pricing_operator', to='authentication.systemuserprofile'), + ), + migrations.AddField( + model_name='pricing', + name='retail_seller_price', + field=models.FloatField(null=True), + ), + migrations.AddField( + model_name='pricing', + name='role', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='poultry_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_poultry_request', to='panel.poultryrequest'), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='decreasing_amount', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='kill_house_factor_payment_remain', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='out', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='previous_amount', + field=models.FloatField(default=0), + ), + 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='provincefactortokillhouse', + name='province_input_amount', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_input_amount_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_wage', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='reason', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouseforpoultry', + name='out', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincefactortokillhouseforpoultry', + name='province_check_req', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_poultry', to='panel.provincecheckoperatorrequest'), + ), + migrations.AddField( + model_name='provincefactortokillhouseforpoultry', + name='weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='clearance_code', + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='reviewer', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='vet_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AddField( + model_name='provinceoperator', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='vet', + name='wallet_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='depositallocation', + name='poultry_share', + field=models.FloatField(default=0, null=True), + ), + migrations.AlterField( + model_name='financialdocument', + name='image', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 291310)), + ), + migrations.AlterField( + model_name='itransaction', + name='payment_code', + field=models.BigIntegerField(default=0, null=True), + ), + migrations.AlterField( + model_name='itransaction', + name='transfer_amount', + field=models.FloatField(null=True), + ), + migrations.AlterField( + model_name='killhousedriver', + name='driver_name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='killhousedriver', + name='health_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 221716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 221623)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 221699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 221675)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 224618)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 224455)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 4, 2, 224491)), + ), + migrations.AlterField( + model_name='poultryhatching', + name='chicken_breed', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='poultryrequest', + name='chicken_breed', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='poultryrequest', + name='order_code', + field=models.BigIntegerField(null=True), + ), + migrations.DeleteModel( + name='Iwallet', + ), + migrations.AddField( + model_name='vetsupervisor', + name='vet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_supervisor', to='panel.vet'), + ), + migrations.AddField( + model_name='vetsupervisor', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supervisor_wallet', to='panel.wallet'), + ), + migrations.AddField( + model_name='vetcheckallocations', + name='kill_house_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='check_kill_house_request', to='panel.killhouserequest'), + ), + migrations.AddField( + model_name='vetcheckallocations', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetcheckallocations_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='vetcheckallocations', + name='vet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_check', to='panel.vet'), + ), + migrations.AddField( + model_name='provinceimportkillhouseoutfactors', + name='kill_house_factor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor_out', to='panel.provincefactortokillhouse'), + ), + migrations.AddField( + model_name='provinceimportkillhouseoutfactors', + name='kill_house_factor_poultry', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor_poultry_out', to='panel.provincefactortokillhouseforpoultry'), + ), + migrations.AddField( + model_name='provinceimportkillhouseoutfactors', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceimportkillhouseoutfactors_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='provinceimportkillhouseoutfactors', + name='province_check', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_request', to='panel.provincecheckoperatorrequest'), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_allow_kill_house_register', to='panel.killhouse'), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregistercar_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='poultryallowcityprovince', + name='poultry', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_allow', to='panel.poultry'), + ), + migrations.AddField( + model_name='killrequestfactor', + name='kill_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='factor_kill_req', to='panel.killrequest'), + ), + migrations.AddField( + model_name='killrequestfactor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequestfactor_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhousepercentage', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percent_killhouse', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhousepercentage', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepercentage_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhousecreditors', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_creditors', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhousecreditors', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecreditors_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhouseassignmentimages', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_images', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhouseassignmentimages', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseassignmentimages_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_allow', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseallowvet_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='financialtransaction', + name='itransaction', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financial_transaction', to='panel.itransaction'), + ), + migrations.AddField( + model_name='financialtransaction', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financialtransaction_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='checkunusualcasualties', + name='complaint', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='losses', to='panel.killhousecomplaint'), + ), + migrations.AddField( + model_name='checkunusualcasualties', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkunusualcasualties_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='checkunusualcasualties', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkunusualcasualties_modifiedby', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/panel/migrations/0015_auto_20230603_2209.py b/panel/migrations/0015_auto_20230603_2209.py new file mode 100644 index 0000000..7130618 --- /dev/null +++ b/panel/migrations/0015_auto_20230603_2209.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-06-03 22:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0014_auto_20230603_2204'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 48, 63321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 975390)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 975256)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 975349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 975306)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 980631)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 980416)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 980464)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 9, 47, 993198)), + ), + ] diff --git a/panel/migrations/0016_auto_20230603_2210.py b/panel/migrations/0016_auto_20230603_2210.py new file mode 100644 index 0000000..05a15ea --- /dev/null +++ b/panel/migrations/0016_auto_20230603_2210.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-06-03 22:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0015_auto_20230603_2209'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 830805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 718145)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 717473)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 718106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 718061)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 723447)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 723142)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 723190)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 3, 22, 10, 34, 740536)), + ), + ] diff --git a/panel/migrations/0017_auto_20230620_2120.py b/panel/migrations/0017_auto_20230620_2120.py new file mode 100644 index 0000000..47ce02d --- /dev/null +++ b/panel/migrations/0017_auto_20230620_2120.py @@ -0,0 +1,245 @@ +# Generated by Django 3.2.13 on 2023-06-20 21: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', '0016_auto_20230603_2210'), + ] + + operations = [ + 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)), + ('percent', models.FloatField(default=0)), + ('quantity', models.BigIntegerField(default=0)), + ('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.AddField( + model_name='killhousepercentage', + name='kill_house_for_killer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killer_kill_house', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhouserequest', + name='editor_traffic_code', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='message', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='priority', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='delete_message', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='number_of_kill_house', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='number_of_poultry', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='rejected_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='waiting_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 251179)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 173229)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 173156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 173211)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 173191)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 176318)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 176149)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 176171)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 20, 21, 20, 22, 186622)), + ), + 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)), + ('state', models.CharField(max_length=50, null=True)), + ('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='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='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)), + ('quantity', models.BigIntegerField(default=0)), + ('allocation_order_code', models.BigIntegerField(default=0)), + ('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)), + ('allow', models.BooleanField(default=False)), + ('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)), + ('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)), + ('allow', models.BooleanField(default=False)), + ('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.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), + ), + ] diff --git a/panel/migrations/0018_auto_20230622_1035.py b/panel/migrations/0018_auto_20230622_1035.py new file mode 100644 index 0000000..32b4d60 --- /dev/null +++ b/panel/migrations/0018_auto_20230622_1035.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-06-22 10:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0017_auto_20230620_2120'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='accepted_real_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='automatic', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 961643)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 881345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 881270)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 881327)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 881307)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 884632)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 884437)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 884488)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 6, 22, 10, 35, 5, 895509)), + ), + ] diff --git a/panel/migrations/0019_auto_20230720_1546.py b/panel/migrations/0019_auto_20230720_1546.py new file mode 100644 index 0000000..c4db4d8 --- /dev/null +++ b/panel/migrations/0019_auto_20230720_1546.py @@ -0,0 +1,1228 @@ +# Generated by Django 3.2.13 on 2023-07-20 15: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 = [ + ('authentication', '0008_auto_20230720_1546'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0018_auto_20230622_1035'), + ] + + operations = [ + 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.AddField( + model_name='admin', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='admin', + name='address', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_address', to='authentication.systemaddress'), + ), + migrations.AddField( + model_name='admin', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='admin', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='admin', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='admin', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='admin', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cityoperator', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cityoperator', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='phone', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='depositallocation', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='depositallocation', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='inspectoroperator', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='inspectoroperator', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='jahad', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='jahad', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='jahad', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='jahad', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='jahad', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='jahad', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhouse', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhouse', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseassignmentimages', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseassignmentimages', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseassignmentimages', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseassignmentimages', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousedriver', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousedriver', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='phone', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseoperator', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouseoperator', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousepercentage', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousepercentage', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousepercentage', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousepercentage', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='accepted_real_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='bar_remover', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousevet', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousevet', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousevet', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousevet', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='allocated_number', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='automatic', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='automatic_debt', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequestfactor', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killrequestfactor', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequestfactor', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killrequestfactor', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequestfactorpayment', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killrequestfactorpayment', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequestfactorpayment', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killrequestfactorpayment', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='active', + field=models.BooleanField(default=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='city_operator', + field=models.CharField(max_length=150, null=True), + ), + migrations.AddField( + model_name='poultry', + name='identity_documents', + field=models.JSONField(null=True), + ), + 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='poultryallowcityprovince', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryallowcityprovince', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryallowcityprovince', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryallowcityprovince', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='archive', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='selling_without_city', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='povinceinspector', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='povinceinspector', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='povinceinspector', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='povinceinspector', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceallowpoultrysellfree', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrysellfree', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceallowpoultrysellfree', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrysellfree', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='state', + field=models.CharField(default='temporary', max_length=50), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='unauthorized_number', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='factor_person_type', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='dont_show_kill_house', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceoperator', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provinceoperator', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='phone', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincialgovernment', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincialgovernment', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='shareofallocation', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='shareofallocation', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='shareofallocation', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='shareofallocation', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='assignableQuantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='vet', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='vet', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vet', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vet', + name='identity_documents', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='vet', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vet', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetfarm', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetfarm', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetfarm', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetfarm', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetfarminspection', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetfarminspection', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetfarminspection', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetfarminspection', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetsupervisor', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='vetsupervisor', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 605343)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 527908)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 527813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 527868)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 527848)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 530974)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 530806)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 530829)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 20, 15, 46, 30, 542364)), + ), + 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='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='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)), + ('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='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, + }, + ), + ] diff --git a/panel/migrations/0020_auto_20230723_1343.py b/panel/migrations/0020_auto_20230723_1343.py new file mode 100644 index 0000000..8c3f81d --- /dev/null +++ b/panel/migrations/0020_auto_20230723_1343.py @@ -0,0 +1,869 @@ +# Generated by Django 3.2.13 on 2023-07-23 13:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0019_auto_20230720_1546'), + ] + + operations = [ + migrations.AddField( + model_name='admin', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='admin', + name='admin_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='admin', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityjahad', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityjahad', + name='city_jahad_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityjahad', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityjahad', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityjahad', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='city_operator_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperator', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='city_operator_check_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='city_operator_system_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='poultry_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='deposit_allocation_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='depositallocation', + name='poultry_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='id_number', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='inspectoroperator', + name='inspector_operator_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='inspectoroperator', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='jahad', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='jahad', + name='jahad_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='jahad', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='jahad', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='jahad', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouse', + name='kill_house_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouse', + name='kill_house_operator_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouse', + name='system_address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='driver_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='kill_house_add_car_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='kill_house_allow_vet_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseallowvet', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='kill_house_check_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='kill_house_kill_house_assingment_information_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='kill_house_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='kill_house_check_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousecheckrequest', + name='province_kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='kill_house_daily_quota_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='killer_kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='kill_house_driver_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='kill_house_factor_to_province_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='province_factor_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='kill_house_operator_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouseoperator', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousepercentage', + name='kill_house_for_killer_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousepercentage', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousepercentage', + name='kill_house_percentage_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='add_car_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='kill_house_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='killhouse_user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='province_kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='province_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousevet', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousevet', + name='kill_house_vet_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousevet', + name='vet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='kill_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='slaughter_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequestfactor', + name='kill_request_factor_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequestfactor', + name='kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequestfactorpayment', + name='kill_request_factor_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killrequestfactorpayment', + name='kill_request_factor_payment_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + 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='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.AddField( + model_name='poultryallowcityprovince', + name='poultry_allow_city_province_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryallowcityprovince', + name='poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='poultry_hatching_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='city_operator_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='poultry_hatching_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='poultry_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='povinceinspector', + name='inspector_operator_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='povinceinspector', + name='poultry_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='povinceinspector', + name='province_inspector_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='pricing', + name='operator_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='pricing', + name='pricing_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceallowkillhouseregistercar', + name='province_allow_kill_house_register_car_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='province_allow_poultry_choose_kill_house_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrysellfree', + name='poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceallowpoultrysellfree', + name='province_allow_poultry_sell_free_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='daily_quota_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='poultry_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='province_auto_allocation_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceautoallocation', + name='province_kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='kill_house_assignment_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='province_check_information_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckinformation', + name='province_operator_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='kill_house_factor_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckkillhousefactor', + name='province_check_kill_house_factor_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='poultry_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='province_operator_check_out_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatoroutrequest', + name='province_operator_system_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='city_request_poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='poultry_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='province_operator_check_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='province_operator_system_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_check_info_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_check_req_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_factor_to_kill_house_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='kill_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='killhouse_user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='province_kill_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='province_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='province_operator_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='provincial_government_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='provincialgovernment', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='shareofallocation', + name='province_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='shareofallocation', + name='share_of_allocation_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='total_poultry_request_quantity_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vet', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vet', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vet', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vet', + name='vet_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vet', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetcheckallocations', + name='kill_house_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetcheckallocations', + name='vet_chick_allocations_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetcheckallocations', + name='vet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='kill_house_request_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='kill_house_vet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetcheckrequest', + name='vet_check_request_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetfarm', + name='poultry_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetfarm', + name='vet_farm_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetfarm', + name='vet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetfarminspection', + name='poultry_hatching_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetfarminspection', + name='vet_farm_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetfarminspection', + name='vet_farm_inspection_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='vet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='vet_superviser_id_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='vetsupervisor', + name='wallet_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='wallet', + name='id_number', + field=models.IntegerField(default=1), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 272687)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 188507)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 188438)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 188490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 188472)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 191759)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 191606)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 191629)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 23, 13, 42, 56, 202582)), + ), + ] diff --git a/panel/migrations/0021_auto_20230726_0957.py b/panel/migrations/0021_auto_20230726_0957.py new file mode 100644 index 0000000..ff1d412 --- /dev/null +++ b/panel/migrations/0021_auto_20230726_0957.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-07-26 09:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0020_auto_20230723_1343'), + ] + + operations = [ + migrations.AddField( + model_name='wallet', + name='province_name', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 840319)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 760409)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 760316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 760370)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 760351)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 763904)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 763486)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 763531)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 7, 26, 9, 57, 28, 775048)), + ), + ] diff --git a/panel/migrations/0022_auto_20230806_2224.py b/panel/migrations/0022_auto_20230806_2224.py new file mode 100644 index 0000000..d4d54fb --- /dev/null +++ b/panel/migrations/0022_auto_20230806_2224.py @@ -0,0 +1,227 @@ +# Generated by Django 3.2.13 on 2023-08-06 22: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), + ('authentication', '0011_auto_20230806_2224'), + ('panel', '0021_auto_20230726_0957'), + ] + + operations = [ + 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)), + ('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')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_wallet', to='panel.wallet')), + ], + 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)), + ('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)), + ('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='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.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 648558)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 555912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 555820)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 555893)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 555857)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 559048)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 558846)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 558886)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 6, 22, 24, 55, 570715)), + ), + 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)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('final_registration', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('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='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='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, + }, + ), + ] diff --git a/panel/migrations/0023_auto_20230807_1546.py b/panel/migrations/0023_auto_20230807_1546.py new file mode 100644 index 0000000..d503853 --- /dev/null +++ b/panel/migrations/0023_auto_20230807_1546.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-08-07 15:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0022_auto_20230806_2224'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='remain_quantity_for_poultry', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 696174)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 610540)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 610454)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 610522)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 610488)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 613865)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 613710)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 613747)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 7, 15, 46, 17, 625849)), + ), + ] diff --git a/panel/migrations/0024_auto_20230810_1359.py b/panel/migrations/0024_auto_20230810_1359.py new file mode 100644 index 0000000..fef7bc7 --- /dev/null +++ b/panel/migrations/0024_auto_20230810_1359.py @@ -0,0 +1,136 @@ +# Generated by Django 3.2.13 on 2023-08-10 13:59 + +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', '0023_auto_20230807_1546'), + ] + + operations = [ + migrations.AddField( + model_name='killhousewarehouse', + name='update_ave_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='update_total_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='update_total_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provinceallowpoultrychoosekillhouse', + name='mandatory', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardallocation', + name='guilds', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_allocation_guilds', to='panel.guilds'), + ), + migrations.AddField( + model_name='stewardallocation', + name='logged_registration_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='registration_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='sell_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='seller_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AddField( + model_name='stewardallocation', + name='system_registration_code', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 312177)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 213016)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 212927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 212998)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 212963)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 216565)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 216382)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 216419)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 13, 58, 57, 228847)), + ), + 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, + }, + ), + ] diff --git a/panel/migrations/0025_auto_20230810_1501.py b/panel/migrations/0025_auto_20230810_1501.py new file mode 100644 index 0000000..836435a --- /dev/null +++ b/panel/migrations/0025_auto_20230810_1501.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-08-10 15:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0024_auto_20230810_1359'), + ] + + operations = [ + migrations.AddField( + model_name='provinceallowpoultrychoosekillhousetotal', + name='mandatory', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 163395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 37106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 37017)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 37088)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 37052)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 40333)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 40146)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 40204)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 10, 15, 1, 6, 53074)), + ), + ] diff --git a/panel/migrations/0026_auto_20230817_1518.py b/panel/migrations/0026_auto_20230817_1518.py new file mode 100644 index 0000000..ca4ead8 --- /dev/null +++ b/panel/migrations/0026_auto_20230817_1518.py @@ -0,0 +1,131 @@ +# Generated by Django 3.2.13 on 2023-08-17 15: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', '0025_auto_20230810_1501'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='kill_house_centers_allocation', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='last_change', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='role', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 242192)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 151365)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 151296)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 151349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 151331)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 155457)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 155282)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 155335)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 17, 15, 18, 54, 167573)), + ), + 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='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, + }, + ), + ] diff --git a/panel/migrations/0027_auto_20230820_1525.py b/panel/migrations/0027_auto_20230820_1525.py new file mode 100644 index 0000000..e9dd9a1 --- /dev/null +++ b/panel/migrations/0027_auto_20230820_1525.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-08-20 15:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0026_auto_20230817_1518'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='chicken_age', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='stewardallocation', + name='real_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='real_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 672063)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 587223)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 587154)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 587206)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 587188)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 590632)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 590481)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 590521)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 20, 15, 25, 25, 601682)), + ), + ] diff --git a/panel/migrations/0028_auto_20230821_1514.py b/panel/migrations/0028_auto_20230821_1514.py new file mode 100644 index 0000000..8bbff37 --- /dev/null +++ b/panel/migrations/0028_auto_20230821_1514.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-08-21 15:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0027_auto_20230820_1525'), + ] + + operations = [ + migrations.AddField( + model_name='killhousepercentage', + name='guilds_quantity', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhousepercentage', + name='last_guilds_update_date', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 138020)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 44755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 44680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 44737)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 44718)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 49535)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 49375)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 49418)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 21, 15, 14, 24, 61447)), + ), + ] diff --git a/panel/migrations/0029_auto_20230827_1543.py b/panel/migrations/0029_auto_20230827_1543.py new file mode 100644 index 0000000..9885005 --- /dev/null +++ b/panel/migrations/0029_auto_20230827_1543.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2023-08-27 15:43 + +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', '0012_auto_20230827_1543'), + ('panel', '0028_auto_20230821_1514'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 4, 26067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 938850)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 938778)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 938833)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 938814)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 942111)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 941976)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 942002)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 27, 15, 43, 3, 954330)), + ), + 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.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, + }, + ), + ] diff --git a/panel/migrations/0030_auto_20230831_1545.py b/panel/migrations/0030_auto_20230831_1545.py new file mode 100644 index 0000000..9601f89 --- /dev/null +++ b/panel/migrations/0030_auto_20230831_1545.py @@ -0,0 +1,87 @@ +# Generated by Django 3.2.13 on 2023-08-31 15: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', '0029_auto_20230827_1543'), + ] + + operations = [ + 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.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 918899)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 837290)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 837188)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 837273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 837251)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 840402)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 840264)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 840292)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 8, 31, 15, 45, 39, 851030)), + ), + 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, + }, + ), + ] diff --git a/panel/migrations/0031_auto_20230902_1110.py b/panel/migrations/0031_auto_20230902_1110.py new file mode 100644 index 0000000..34dee85 --- /dev/null +++ b/panel/migrations/0031_auto_20230902_1110.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-09-02 11:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0030_auto_20230831_1545'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 519384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 435029)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 434958)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 435011)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 434993)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 438201)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 438050)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 438078)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 11, 10, 43, 449075)), + ), + ] diff --git a/panel/migrations/0032_auto_20230902_1526.py b/panel/migrations/0032_auto_20230902_1526.py new file mode 100644 index 0000000..87200d0 --- /dev/null +++ b/panel/migrations/0032_auto_20230902_1526.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-02 15:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0031_auto_20230902_1110'), + ] + + operations = [ + migrations.AddField( + model_name='killhousepercentage', + name='guilds_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 822678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 730453)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 730343)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 730431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 730394)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 734259)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 734121)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 734151)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 2, 15, 26, 6, 746374)), + ), + ] diff --git a/panel/migrations/0033_auto_20230904_1058.py b/panel/migrations/0033_auto_20230904_1058.py new file mode 100644 index 0000000..04628d4 --- /dev/null +++ b/panel/migrations/0033_auto_20230904_1058.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-04 10:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0032_auto_20230902_1526'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='latest_hatching_change', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 341976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 256125)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 256056)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 256108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 256090)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 259423)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 259290)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 259315)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 4, 10, 58, 7, 271283)), + ), + ] diff --git a/panel/migrations/0034_auto_20230911_1543.py b/panel/migrations/0034_auto_20230911_1543.py new file mode 100644 index 0000000..0ffbde8 --- /dev/null +++ b/panel/migrations/0034_auto_20230911_1543.py @@ -0,0 +1,98 @@ +# Generated by Django 3.2.13 on 2023-09-11 15:43 + +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', '0033_auto_20230904_1058'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='archive_by_province', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='depositor', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='wage_pay', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 622630)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 535237)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 535169)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 535221)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 535203)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 538639)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 538501)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 538524)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 11, 15, 43, 29, 550206)), + ), + 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, + }, + ), + ] diff --git a/panel/migrations/0035_auto_20230912_1431.py b/panel/migrations/0035_auto_20230912_1431.py new file mode 100644 index 0000000..5cdeeb8 --- /dev/null +++ b/panel/migrations/0035_auto_20230912_1431.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-12 14:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0034_auto_20230911_1543'), + ] + + operations = [ + migrations.AddField( + model_name='killhousedriver', + name='type', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 222714)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 133159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 133088)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 133143)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 133124)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 136592)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 136432)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 136455)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 12, 14, 31, 4, 148679)), + ), + ] diff --git a/panel/migrations/0036_auto_20230927_1031.py b/panel/migrations/0036_auto_20230927_1031.py new file mode 100644 index 0000000..1a912b1 --- /dev/null +++ b/panel/migrations/0036_auto_20230927_1031.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2023-09-27 10:31 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0035_auto_20230912_1431'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='direct_buying_message', + field=models.CharField(max_length=500, null=True), + ), + 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='killrequest', + name='previous_kill_capacity', + field=models.IntegerField(default=0, null=True), + ), + 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, 27, 10, 31, 50, 493666)), + ), + 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, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 443286)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 31, 50, 459822)), + ), + ] diff --git a/panel/migrations/0037_auto_20230927_1508.py b/panel/migrations/0037_auto_20230927_1508.py new file mode 100644 index 0000000..a0879bc --- /dev/null +++ b/panel/migrations/0037_auto_20230927_1508.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-09-27 15:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0036_auto_20230927_1031'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='direct_buying_buyer_info', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='direct_buying_kill_place', + field=models.CharField(max_length=100, null=True), + ), + 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, 15, 8, 26, 383193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 320698)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 8, 26, 336317)), + ), + ] diff --git a/panel/migrations/0038_auto_20230928_1547.py b/panel/migrations/0038_auto_20230928_1547.py new file mode 100644 index 0000000..94ab896 --- /dev/null +++ b/panel/migrations/0038_auto_20230928_1547.py @@ -0,0 +1,106 @@ +# Generated by Django 3.2.13 on 2023-09-28 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', '0037_auto_20230927_1508'), + ] + + 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, 47, 54, 968516)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 920479)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 47, 54, 936104)), + ), + 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/0039_auto_20231002_1559.py b/panel/migrations/0039_auto_20231002_1559.py new file mode 100644 index 0000000..1581fdb --- /dev/null +++ b/panel/migrations/0039_auto_20231002_1559.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-10-02 15:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0038_auto_20230928_1547'), + ] + + operations = [ + migrations.AddField( + model_name='killhouseaddcar', + name='active_state', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhousedriver', + name='active_state', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 652994)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 15, 59, 31, 621738)), + ), + ] diff --git a/panel/migrations/0040_auto_20231004_1615.py b/panel/migrations/0040_auto_20231004_1615.py new file mode 100644 index 0000000..b8dd816 --- /dev/null +++ b/panel/migrations/0040_auto_20231004_1615.py @@ -0,0 +1,121 @@ +# Generated by Django 3.2.13 on 2023-10-04 16: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', '0039_auto_20231002_1559'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='kill_house_register', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='province_accept_state', + field=models.CharField(default='accepted', max_length=20), + ), + migrations.AddField( + model_name='guilds', + name='province_message', + field=models.CharField(max_length=500, null=True), + ), + 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, 16, 15, 54, 901103)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 796582)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 796582)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 796582)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 796582)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 800578)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 799577)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 799577)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 16, 15, 54, 811578)), + ), + 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/0041_auto_20231007_1416.py b/panel/migrations/0041_auto_20231007_1416.py new file mode 100644 index 0000000..11fcf11 --- /dev/null +++ b/panel/migrations/0041_auto_20231007_1416.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-10-07 14:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0040_auto_20231004_1615'), + ] + + 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, 14, 16, 31, 756257)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 885067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 885067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 885067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 885067)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 890060)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 890060)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 890060)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 14, 16, 30, 934020)), + ), + ] diff --git a/panel/migrations/0042_auto_20231010_1504.py b/panel/migrations/0042_auto_20231010_1504.py new file mode 100644 index 0000000..eee9b84 --- /dev/null +++ b/panel/migrations/0042_auto_20231010_1504.py @@ -0,0 +1,105 @@ +# Generated by Django 3.2.13 on 2023-10-10 15:04 + +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', '0013_auto_20231010_1504'), + ('panel', '0041_auto_20231007_1416'), + ] + + 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, 15, 4, 25, 403432)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 357651)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 15, 4, 25, 372166)), + ), + 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')), + ('vet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_city_vet', to='panel.vet')), + ('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/0043_auto_20231012_0852.py b/panel/migrations/0043_auto_20231012_0852.py new file mode 100644 index 0000000..5d1990b --- /dev/null +++ b/panel/migrations/0043_auto_20231012_0852.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2023-10-12 08: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', '0042_auto_20231010_1504'), + ] + + 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, 12, 8, 51, 54, 680236)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 605860)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 605365)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 605365)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 605365)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 608319)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 608209)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 608209)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 12, 8, 51, 54, 615103)), + ), + 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/0044_auto_20231018_1446.py b/panel/migrations/0044_auto_20231018_1446.py new file mode 100644 index 0000000..0281733 --- /dev/null +++ b/panel/migrations/0044_auto_20231018_1446.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2023-10-18 14:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0043_auto_20231012_0852'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='prev_total_amount', + field=models.FloatField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='total_amount', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='total_amount_editor', + field=models.JSONField(null=True), + ), + 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, 18, 14, 46, 45, 736744)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 685408)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 685408)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 685408)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 685408)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 687401)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 687401)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 687401)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 18, 14, 46, 45, 693990)), + ), + ] diff --git a/panel/migrations/0045_auto_20231029_1833.py b/panel/migrations/0045_auto_20231029_1833.py new file mode 100644 index 0000000..e7a56e8 --- /dev/null +++ b/panel/migrations/0045_auto_20231029_1833.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2023-10-29 18: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', '0044_auto_20231018_1446'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 608860)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 29, 18, 32, 59, 552297)), + ), + 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/0046_auto_20231031_1821.py b/panel/migrations/0046_auto_20231031_1821.py new file mode 100644 index 0000000..88d5562 --- /dev/null +++ b/panel/migrations/0046_auto_20231031_1821.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2023-10-31 18:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0045_auto_20231029_1833'), + ] + + operations = [ + migrations.AddField( + model_name='wagepayment', + name='cardHolderPan', + field=models.CharField(max_length=100, null=True), + ), + 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, 18, 21, 28, 783670)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 18, 21, 28, 752374)), + ), + ] diff --git a/panel/migrations/0047_auto_20231103_1549.py b/panel/migrations/0047_auto_20231103_1549.py new file mode 100644 index 0000000..8d676c8 --- /dev/null +++ b/panel/migrations/0047_auto_20231103_1549.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-03 15:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0046_auto_20231031_1821'), + ] + + 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, 49, 53, 396850)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 338902)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 338902)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 338902)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 338902)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 340900)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 340900)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 340900)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 49, 53, 348894)), + ), + ] diff --git a/panel/migrations/0048_auto_20231104_1456.py b/panel/migrations/0048_auto_20231104_1456.py new file mode 100644 index 0000000..fc77a84 --- /dev/null +++ b/panel/migrations/0048_auto_20231104_1456.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2023-11-04 14:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0047_auto_20231103_1549'), + ] + + 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.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, 14, 56, 32, 739732)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 692882)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 14, 56, 32, 708482)), + ), + ] diff --git a/panel/migrations/0049_auto_20231105_2224.py b/panel/migrations/0049_auto_20231105_2224.py new file mode 100644 index 0000000..4013419 --- /dev/null +++ b/panel/migrations/0049_auto_20231105_2224.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-05 22:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0048_auto_20231104_1456'), + ] + + 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, 22, 24, 2, 221752)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 176747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 176747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 176747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 176747)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 179747)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 178747)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 179747)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 22, 24, 2, 186746)), + ), + ] diff --git a/panel/migrations/0050_auto_20231107_1925.py b/panel/migrations/0050_auto_20231107_1925.py new file mode 100644 index 0000000..eb4d38d --- /dev/null +++ b/panel/migrations/0050_auto_20231107_1925.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2023-11-07 19: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', '0049_auto_20231105_2224'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 604020)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 7, 19, 25, 1, 557124)), + ), + 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')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_automatic_allocation', to='panel.killhouse')), + ('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/0051_auto_20231108_1546.py b/panel/migrations/0051_auto_20231108_1546.py new file mode 100644 index 0000000..88e2614 --- /dev/null +++ b/panel/migrations/0051_auto_20231108_1546.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2023-11-08 15:46 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0050_auto_20231107_1925'), + ] + + 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, 15, 46, 37, 901735)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 780929)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 780929)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 780929)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 780929)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 787008)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 787008)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 787008)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 15, 46, 37, 802149)), + ), + ] diff --git a/panel/migrations/0052_auto_20231111_1604.py b/panel/migrations/0052_auto_20231111_1604.py new file mode 100644 index 0000000..42fce5f --- /dev/null +++ b/panel/migrations/0052_auto_20231111_1604.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-11 16:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0051_auto_20231108_1546'), + ] + + 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, 16, 4, 49, 367678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 324839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 324839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 324839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 324839)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 327089)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 327089)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 327089)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 16, 4, 49, 332675)), + ), + ] diff --git a/panel/migrations/0053_auto_20231113_1424.py b/panel/migrations/0053_auto_20231113_1424.py new file mode 100644 index 0000000..1fe0d9a --- /dev/null +++ b/panel/migrations/0053_auto_20231113_1424.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-13 14:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0052_auto_20231111_1604'), + ] + + 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, 13, 14, 24, 11, 766253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 713303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 713303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 713303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 713303)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 714302)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 714302)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 714302)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 13, 14, 24, 11, 721295)), + ), + ] diff --git a/panel/migrations/0054_auto_20231117_1138.py b/panel/migrations/0054_auto_20231117_1138.py new file mode 100644 index 0000000..6701c43 --- /dev/null +++ b/panel/migrations/0054_auto_20231117_1138.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-11-17 11:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0053_auto_20231113_1424'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 879979)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 800123)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 17, 11, 38, 16, 810415)), + ), + ] diff --git a/panel/migrations/0055_auto_20231122_1549.py b/panel/migrations/0055_auto_20231122_1549.py new file mode 100644 index 0000000..e024614 --- /dev/null +++ b/panel/migrations/0055_auto_20231122_1549.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-22 15:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0054_auto_20231117_1138'), + ] + + 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, 15, 49, 2, 419339)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 236930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 234159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 234159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 234159)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 244526)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 244526)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 244526)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 15, 49, 2, 286740)), + ), + ] diff --git a/panel/migrations/0056_auto_20231127_1533.py b/panel/migrations/0056_auto_20231127_1533.py new file mode 100644 index 0000000..88d3f8e --- /dev/null +++ b/panel/migrations/0056_auto_20231127_1533.py @@ -0,0 +1,129 @@ +# Generated by Django 3.2.13 on 2023-11-27 15: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', '0055_auto_20231122_1549'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryhatching', + name='temp_killed_quantity', + ), + 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_average_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_commitment', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='free_sale_in_province', + field=models.BooleanField(default=False), + ), + 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.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, 15, 33, 36, 969101)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 928100)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 928100)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 928100)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 928100)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 929101)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 929101)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 929101)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 33, 36, 935101)), + ), + 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/0057_auto_20231130_1506.py b/panel/migrations/0057_auto_20231130_1506.py new file mode 100644 index 0000000..7c04782 --- /dev/null +++ b/panel/migrations/0057_auto_20231130_1506.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2023-11-30 15:06 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0056_auto_20231127_1533'), + ] + + 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='free_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='governmental_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_commitment_quantity', + field=models.FloatField(default=0), + ), + 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, 30, 15, 6, 31, 224053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 30, 15, 6, 31, 192762)), + ), + ] diff --git a/panel/migrations/0058_auto_20231205_1348.py b/panel/migrations/0058_auto_20231205_1348.py new file mode 100644 index 0000000..30858f5 --- /dev/null +++ b/panel/migrations/0058_auto_20231205_1348.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2023-12-05 13:48 + +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_20231205_1348'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0057_auto_20231130_1506'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 532369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 382508)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 382508)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 382508)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 382508)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 390500)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 389501)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 389501)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 48, 10, 410482)), + ), + 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/0059_auto_20231210_1416.py b/panel/migrations/0059_auto_20231210_1416.py new file mode 100644 index 0000000..a26e741 --- /dev/null +++ b/panel/migrations/0059_auto_20231210_1416.py @@ -0,0 +1,129 @@ +# Generated by Django 3.2.13 on 2023-12-10 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 = [ + ('authentication', '0017_auto_20231210_1416'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0058_auto_20231205_1348'), + ] + + 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.AddField( + model_name='poultryhatching', + name='extra_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='amount', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='financial_operation', + field=models.CharField(max_length=100, null=True), + ), + 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.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, 10, 14, 16, 16, 857900)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 815900)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 815900)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 815900)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 815900)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 816900)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 816900)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 816900)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 16, 16, 822901)), + ), + 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/0060_auto_20231211_2019.py b/panel/migrations/0060_auto_20231211_2019.py new file mode 100644 index 0000000..717bc4f --- /dev/null +++ b/panel/migrations/0060_auto_20231211_2019.py @@ -0,0 +1,133 @@ +# Generated by Django 3.2.13 on 2023-12-11 20: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), + ('authentication', '0018_auto_20231211_2019'), + ('panel', '0059_auto_20231210_1416'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='steward_register', + field=models.BooleanField(default=False), + ), + 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, 20, 18, 56, 832931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 753265)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 753265)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 753265)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 753265)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 756202)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 756202)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 756202)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 20, 18, 56, 766977)), + ), + 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/0061_auto_20231212_1952.py b/panel/migrations/0061_auto_20231212_1952.py new file mode 100644 index 0000000..2d406bf --- /dev/null +++ b/panel/migrations/0061_auto_20231212_1952.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2023-12-12 19:52 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0060_auto_20231211_2019'), + ] + + 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.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, 19, 52, 47, 781662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 657452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 657452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 657452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 657452)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 666632)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 666632)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 666632)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 19, 52, 47, 683066)), + ), + ] diff --git a/panel/migrations/0062_auto_20231214_2314.py b/panel/migrations/0062_auto_20231214_2314.py new file mode 100644 index 0000000..a34d9c0 --- /dev/null +++ b/panel/migrations/0062_auto_20231214_2314.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2023-12-14 23:14 + +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', '0019_auto_20231214_2314'), + ('panel', '0061_auto_20231212_1952'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 912725)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 848184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 848184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 848184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 848184)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 850183)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 850183)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 850183)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 23, 14, 40, 858187)), + ), + 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')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_pos', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0063_auto_20231217_1424.py b/panel/migrations/0063_auto_20231217_1424.py new file mode 100644 index 0000000..ad3f00b --- /dev/null +++ b/panel/migrations/0063_auto_20231217_1424.py @@ -0,0 +1,110 @@ +# Generated by Django 3.2.13 on 2023-12-17 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', '0062_auto_20231214_2314'), + ] + + 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.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, 17, 14, 24, 41, 487031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 435033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 434032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 434032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 434032)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 437033)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 437033)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 437033)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 17, 14, 24, 41, 445033)), + ), + 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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0064_auto_20231225_1748.py b/panel/migrations/0064_auto_20231225_1748.py new file mode 100644 index 0000000..8a40971 --- /dev/null +++ b/panel/migrations/0064_auto_20231225_1748.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-25 17:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0063_auto_20231217_1424'), + ] + + 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, 17, 48, 7, 829337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 17, 48, 7, 783146)), + ), + ] diff --git a/panel/migrations/0065_auto_20231226_1618.py b/panel/migrations/0065_auto_20231226_1618.py new file mode 100644 index 0000000..4846aa7 --- /dev/null +++ b/panel/migrations/0065_auto_20231226_1618.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-26 16:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0064_auto_20231225_1748'), + ] + + 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, 16, 18, 1, 129770)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 68097)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 16, 18, 1, 83228)), + ), + ] diff --git a/panel/migrations/0066_auto_20231227_1558.py b/panel/migrations/0066_auto_20231227_1558.py new file mode 100644 index 0000000..e2ba1df --- /dev/null +++ b/panel/migrations/0066_auto_20231227_1558.py @@ -0,0 +1,137 @@ +# Generated by Django 3.2.13 on 2023-12-27 15:58 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0065_auto_20231226_1618'), + ] + + 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.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, 58, 34, 385969)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 321376)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 321376)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 321376)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 321376)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 323382)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 323382)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 323382)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 58, 34, 330381)), + ), + ] diff --git a/panel/migrations/0067_auto_20240102_1532.py b/panel/migrations/0067_auto_20240102_1532.py new file mode 100644 index 0000000..062a4b8 --- /dev/null +++ b/panel/migrations/0067_auto_20240102_1532.py @@ -0,0 +1,115 @@ +# Generated by Django 3.2.13 on 2024-01-02 15:32 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0066_auto_20231227_1558'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='quarantine_code_state', + field=models.CharField(max_length=500, null=True), + ), + 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.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.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.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(2024, 1, 2, 15, 32, 2, 764568)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 638706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 638706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 638706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 638706)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 641707)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 641707)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 641707)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 15, 32, 2, 658709)), + ), + ] diff --git a/panel/migrations/0068_auto_20240103_1635.py b/panel/migrations/0068_auto_20240103_1635.py new file mode 100644 index 0000000..ddfc135 --- /dev/null +++ b/panel/migrations/0068_auto_20240103_1635.py @@ -0,0 +1,111 @@ +# Generated by Django 3.2.13 on 2024-01-03 16:35 + +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', '0067_auto_20240102_1532'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryrequest', + name='clearance_code', + ), + migrations.AddField( + model_name='poultryrequest', + name='out_province_driver_info', + field=models.JSONField(null=True), + ), + 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, 16, 35, 28, 50026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952331)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952331)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952331)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952331)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952875)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952875)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952875)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 16, 35, 27, 952875)), + ), + 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/0069_auto_20240108_1233.py b/panel/migrations/0069_auto_20240108_1233.py new file mode 100644 index 0000000..0c494ac --- /dev/null +++ b/panel/migrations/0069_auto_20240108_1233.py @@ -0,0 +1,171 @@ +# Generated by Django 3.2.13 on 2024-01-08 12: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), + ('authentication', '0020_auto_20240108_1233'), + ('panel', '0068_auto_20240103_1635'), + ] + + 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.AddField( + model_name='posmachine', + name='active', + field=models.BooleanField(default=True), + ), + 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.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, 12, 32, 58, 453049)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 390500)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 12, 32, 58, 406170)), + ), + 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, + }, + ), + 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, + }, + ), + 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)), + ('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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0070_auto_20240108_2153.py b/panel/migrations/0070_auto_20240108_2153.py new file mode 100644 index 0000000..5eb3376 --- /dev/null +++ b/panel/migrations/0070_auto_20240108_2153.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-08 21:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0069_auto_20240108_1233'), + ] + + 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, 52, 48, 306896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 181013)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 181013)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 181013)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 181013)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 185009)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 184009)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 185009)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 52, 48, 201993)), + ), + ] diff --git a/panel/migrations/0071_auto_20240108_2302.py b/panel/migrations/0071_auto_20240108_2302.py new file mode 100644 index 0000000..6cf0676 --- /dev/null +++ b/panel/migrations/0071_auto_20240108_2302.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-08 23:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0070_auto_20240108_2153'), + ] + + 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, 23, 2, 36, 628255)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 410458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 410458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 410458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 410458)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 414454)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 414454)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 414454)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 2, 36, 455417)), + ), + ] diff --git a/panel/migrations/0072_auto_20240108_2351.py b/panel/migrations/0072_auto_20240108_2351.py new file mode 100644 index 0000000..645acaf --- /dev/null +++ b/panel/migrations/0072_auto_20240108_2351.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-01-08 23: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', '0071_auto_20240108_2302'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 526032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 334210)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 334210)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 334210)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 334210)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 338207)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 338207)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 338207)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 51, 34, 353194)), + ), + 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/0073_auto_20240109_1537.py b/panel/migrations/0073_auto_20240109_1537.py new file mode 100644 index 0000000..66d5987 --- /dev/null +++ b/panel/migrations/0073_auto_20240109_1537.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-01-09 15:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0072_auto_20240108_2351'), + ] + + 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, 15, 37, 14, 795688)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 748306)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 15, 37, 14, 765467)), + ), + ] diff --git a/panel/migrations/0074_auto_20240110_2021.py b/panel/migrations/0074_auto_20240110_2021.py new file mode 100644 index 0000000..b44a285 --- /dev/null +++ b/panel/migrations/0074_auto_20240110_2021.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2024-01-10 20: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', '0021_auto_20240110_2021'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0073_auto_20240109_1537'), + ] + + 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, 20, 21, 13, 867113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 825843)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 825843)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 825843)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 825843)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 827849)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 827849)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 827849)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 20, 21, 13, 827849)), + ), + 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/0075_auto_20240111_1601.py b/panel/migrations/0075_auto_20240111_1601.py new file mode 100644 index 0000000..3891b44 --- /dev/null +++ b/panel/migrations/0075_auto_20240111_1601.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-11 16:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0074_auto_20240110_2021'), + ] + + 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, 16, 1, 39, 153984)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 42086)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 42086)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 42086)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 42086)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 45084)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 45084)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 45084)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 16, 1, 39, 59071)), + ), + ] diff --git a/panel/migrations/0076_auto_20240114_1420.py b/panel/migrations/0076_auto_20240114_1420.py new file mode 100644 index 0000000..da35357 --- /dev/null +++ b/panel/migrations/0076_auto_20240114_1420.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-14 14:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0075_auto_20240111_1601'), + ] + + operations = [ + 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, 14, 20, 42, 297536)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 71062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 71062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 71062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 71062)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 76675)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 76675)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 76675)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 14, 20, 42, 96758)), + ), + ] diff --git a/panel/migrations/0077_auto_20240114_1535.py b/panel/migrations/0077_auto_20240114_1535.py new file mode 100644 index 0000000..90cd07a --- /dev/null +++ b/panel/migrations/0077_auto_20240114_1535.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-01-14 15:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0076_auto_20240114_1420'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='condition', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='guilds', + name='description_condition', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 214322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 26079)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 26079)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 26079)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 26079)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 31448)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 31448)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 31448)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 15, 35, 36, 61456)), + ), + ] diff --git a/panel/migrations/0078_auto_20240115_1312.py b/panel/migrations/0078_auto_20240115_1312.py new file mode 100644 index 0000000..abad26f --- /dev/null +++ b/panel/migrations/0078_auto_20240115_1312.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-15 13:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0077_auto_20240114_1535'), + ] + + 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, 13, 12, 42, 768587)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 601744)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 600745)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 601744)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 601744)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 606740)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 606740)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 606740)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 13, 12, 42, 628717)), + ), + ] diff --git a/panel/migrations/0079_auto_20240117_1827.py b/panel/migrations/0079_auto_20240117_1827.py new file mode 100644 index 0000000..e780663 --- /dev/null +++ b/panel/migrations/0079_auto_20240117_1827.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-01-17 18:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0078_auto_20240115_1312'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 486434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 246403)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 246403)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 246403)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 246403)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 255797)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 255797)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 255797)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 17, 18, 26, 45, 277294)), + ), + ] diff --git a/panel/migrations/0080_auto_20240118_1530.py b/panel/migrations/0080_auto_20240118_1530.py new file mode 100644 index 0000000..2eae335 --- /dev/null +++ b/panel/migrations/0080_auto_20240118_1530.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-18 15:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0079_auto_20240117_1827'), + ] + + 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, 15, 30, 7, 675988)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 631026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 631026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 631026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 631026)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 633025)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 633025)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 633025)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 15, 30, 7, 639025)), + ), + ] diff --git a/panel/migrations/0081_auto_20240121_1526.py b/panel/migrations/0081_auto_20240121_1526.py new file mode 100644 index 0000000..ae9ef31 --- /dev/null +++ b/panel/migrations/0081_auto_20240121_1526.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-01-21 15:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0080_auto_20240118_1530'), + ] + + 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, 15, 26, 7, 908217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 726225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 725230)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 726225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 726225)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 731223)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 731223)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 731223)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 15, 26, 7, 760222)), + ), + ] diff --git a/panel/migrations/0082_auto_20240123_1602.py b/panel/migrations/0082_auto_20240123_1602.py new file mode 100644 index 0000000..a9b60a0 --- /dev/null +++ b/panel/migrations/0082_auto_20240123_1602.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2024-01-23 16: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', '0081_auto_20240121_1526'), + ] + + 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, 16, 2, 24, 776232)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 95237)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 95237)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 95237)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 95237)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 106159)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 106159)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 106159)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 16, 2, 24, 233534)), + ), + 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/0083_auto_20240127_1542.py b/panel/migrations/0083_auto_20240127_1542.py new file mode 100644 index 0000000..8a1927e --- /dev/null +++ b/panel/migrations/0083_auto_20240127_1542.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-01-27 15:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0082_auto_20240123_1602'), + ] + + 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, 15, 42, 19, 437250)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 374305)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 374305)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 374305)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 374305)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 376303)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 376303)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 376303)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 15, 42, 19, 385296)), + ), + ] diff --git a/panel/migrations/0084_auto_20240130_1115.py b/panel/migrations/0084_auto_20240130_1115.py new file mode 100644 index 0000000..2a214b8 --- /dev/null +++ b/panel/migrations/0084_auto_20240130_1115.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2024-01-30 11: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', '0083_auto_20240127_1542'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 323650)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 180757)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 180757)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 180757)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 180757)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 196382)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 196382)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 196382)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 11, 15, 17, 212008)), + ), + 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/0085_auto_20240206_1006.py b/panel/migrations/0085_auto_20240206_1006.py new file mode 100644 index 0000000..171d429 --- /dev/null +++ b/panel/migrations/0085_auto_20240206_1006.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-06 10:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0084_auto_20240130_1115'), + ] + + 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, 6, 10, 6, 0, 848480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 10, 6, 0, 785983)), + ), + ] diff --git a/panel/migrations/0086_auto_20240206_1550.py b/panel/migrations/0086_auto_20240206_1550.py new file mode 100644 index 0000000..452f7ba --- /dev/null +++ b/panel/migrations/0086_auto_20240206_1550.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-02-06 15:50 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0085_auto_20240206_1006'), + ] + + 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.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, 49, 56, 560981)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 938005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 938005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 938005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 938005)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 970985)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 970985)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 55, 970985)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 49, 56, 125984)), + ), + ] diff --git a/panel/migrations/0087_auto_20240207_1537.py b/panel/migrations/0087_auto_20240207_1537.py new file mode 100644 index 0000000..cacb758 --- /dev/null +++ b/panel/migrations/0087_auto_20240207_1537.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2024-02-07 15:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0086_auto_20240206_1550'), + ] + + 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, 15, 37, 3, 78873)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 32871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 32871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 32871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 32871)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 34871)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 34871)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 34871)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 15, 37, 3, 40871)), + ), + ] diff --git a/panel/migrations/0088_auto_20240214_0957.py b/panel/migrations/0088_auto_20240214_0957.py new file mode 100644 index 0000000..6282867 --- /dev/null +++ b/panel/migrations/0088_auto_20240214_0957.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-02-14 09:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0087_auto_20240207_1537'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 219360)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 174321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 174321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 174321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 174321)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 176320)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 176320)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 176320)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 57, 14, 182360)), + ), + ] diff --git a/panel/migrations/0089_auto_20240214_1000.py b/panel/migrations/0089_auto_20240214_1000.py new file mode 100644 index 0000000..4d3eb79 --- /dev/null +++ b/panel/migrations/0089_auto_20240214_1000.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-14 10:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0088_auto_20240214_0957'), + ] + + 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, 0, 33, 119330)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 21330)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 21330)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 21330)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 21330)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 27327)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 27327)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 27327)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 0, 33, 39326)), + ), + ] diff --git a/panel/migrations/0090_auto_20240214_1203.py b/panel/migrations/0090_auto_20240214_1203.py new file mode 100644 index 0000000..fb23949 --- /dev/null +++ b/panel/migrations/0090_auto_20240214_1203.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-02-14 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', '0089_auto_20240214_1000'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 350974)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 127182)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 127182)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 127182)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 127182)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 131178)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 131178)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 131178)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 12, 2, 49, 148162)), + ), + 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/0091_auto_20240220_1536.py b/panel/migrations/0091_auto_20240220_1536.py new file mode 100644 index 0000000..609658d --- /dev/null +++ b/panel/migrations/0091_auto_20240220_1536.py @@ -0,0 +1,106 @@ +# Generated by Django 3.2.13 on 2024-02-20 15:36 + +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', '0023_auto_20240220_1536'), + ('panel', '0090_auto_20240214_1203'), + ] + + 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, 15, 36, 25, 497762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 445766)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 445766)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 445766)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 445766)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 448765)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 448765)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 448765)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 15, 36, 25, 458763)), + ), + 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, + }, + ), + 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/0092_auto_20240221_1534.py b/panel/migrations/0092_auto_20240221_1534.py new file mode 100644 index 0000000..b463771 --- /dev/null +++ b/panel/migrations/0092_auto_20240221_1534.py @@ -0,0 +1,115 @@ +# Generated by Django 3.2.13 on 2024-02-21 15: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', '0091_auto_20240220_1536'), + ] + + operations = [ + 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, + }, + ), + 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, 15, 33, 57, 617852)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 475864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 475864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 475864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 475864)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 483415)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 483415)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 483415)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 33, 57, 502484)), + ), + 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)), + ('state', models.CharField(default='pending', max_length=20)), + ('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')), + ('kill_house_ware_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_kill_house_ware_house', to='panel.killhousewarehouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhouseallocations_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0093_auto_20240226_1550.py b/panel/migrations/0093_auto_20240226_1550.py new file mode 100644 index 0000000..bcab1d4 --- /dev/null +++ b/panel/migrations/0093_auto_20240226_1550.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-02-26 15:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0092_auto_20240221_1534'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='date', + field=models.DateTimeField(null=True), + ), + 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, 15, 49, 48, 952661)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 814790)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 814790)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 814790)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 814790)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 818787)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 818787)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 818787)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 49, 48, 904706)), + ), + ] diff --git a/panel/migrations/0094_auto_20240227_1032.py b/panel/migrations/0094_auto_20240227_1032.py new file mode 100644 index 0000000..d57261d --- /dev/null +++ b/panel/migrations/0094_auto_20240227_1032.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2024-02-27 10: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', '0093_auto_20240226_1550'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='freezing', + field=models.BooleanField(default=False), + ), + 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, 27, 10, 32, 40, 934624)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 856623)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 856623)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 856623)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 856623)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 859624)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 859624)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 859624)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 10, 32, 40, 869623)), + ), + 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/0095_auto_20240227_1550.py b/panel/migrations/0095_auto_20240227_1550.py new file mode 100644 index 0000000..cda02c6 --- /dev/null +++ b/panel/migrations/0095_auto_20240227_1550.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-02-27 15:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0094_auto_20240227_1032'), + ] + + 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, 15, 50, 21, 781825)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 658939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 658939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 658939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 658939)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 662937)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 662937)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 662937)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 15, 50, 21, 680919)), + ), + ] diff --git a/panel/migrations/0096_auto_20240304_0929.py b/panel/migrations/0096_auto_20240304_0929.py new file mode 100644 index 0000000..f9f8649 --- /dev/null +++ b/panel/migrations/0096_auto_20240304_0929.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-03-04 09:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0095_auto_20240227_1550'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='ware_house_input_type', + field=models.CharField(max_length=100, null=True), + ), + 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, 4, 9, 28, 57, 796279)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 595740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 595740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 595740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 595740)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 599737)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 598739)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 598739)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 4, 9, 28, 57, 618679)), + ), + ] diff --git a/panel/migrations/0097_auto_20240309_1145.py b/panel/migrations/0097_auto_20240309_1145.py new file mode 100644 index 0000000..5259b81 --- /dev/null +++ b/panel/migrations/0097_auto_20240309_1145.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-03-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', '0096_auto_20240304_0929'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 254819)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 198871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 198871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 198871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 198871)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 200870)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 200870)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 200870)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 11, 45, 49, 208861)), + ), + 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/0098_auto_20240311_1344.py b/panel/migrations/0098_auto_20240311_1344.py new file mode 100644 index 0000000..47509f0 --- /dev/null +++ b/panel/migrations/0098_auto_20240311_1344.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-11 13:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0097_auto_20240309_1145'), + ] + + 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, 13, 43, 49, 995765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 896855)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 896855)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 896855)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 896855)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 900852)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 899852)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 900852)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 13, 43, 49, 915838)), + ), + ] diff --git a/panel/migrations/0099_auto_20240312_1205.py b/panel/migrations/0099_auto_20240312_1205.py new file mode 100644 index 0000000..5d9c125 --- /dev/null +++ b/panel/migrations/0099_auto_20240312_1205.py @@ -0,0 +1,88 @@ +# Generated by Django 3.2.13 on 2024-03-12 12: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', '0098_auto_20240311_1344'), + ] + + 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, 12, 5, 35, 353567)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 297620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 297620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 297620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 297620)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 299618)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 299618)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 299618)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 12, 5, 35, 307610)), + ), + 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/0100_auto_20240315_2226.py b/panel/migrations/0100_auto_20240315_2226.py new file mode 100644 index 0000000..d508403 --- /dev/null +++ b/panel/migrations/0100_auto_20240315_2226.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-03-15 22: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', '0099_auto_20240312_1205'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 773487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 718538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 718538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 718538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 718538)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 720536)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 720536)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 720536)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 26, 11, 728528)), + ), + 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/0101_operationlimitation_vet_check_kill_house_assignment_limitation_and_more.py b/panel/migrations/0101_operationlimitation_vet_check_kill_house_assignment_limitation_and_more.py new file mode 100644 index 0000000..83964f6 --- /dev/null +++ b/panel/migrations/0101_operationlimitation_vet_check_kill_house_assignment_limitation_and_more.py @@ -0,0 +1,1457 @@ +# Generated by Django 5.0.3 on 2024-03-18 13:52 + +import datetime +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0100_auto_20240315_2226'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='operationlimitation', + name='vet_check_kill_house_assignment_limitation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='additionalproducts', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='additionalproducts', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='admin', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='admin', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='announcements', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='announcements', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='approvedprice', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='approvedprice', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='areaactivity', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='areaactivity', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='autoacceptprovincekillrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='autoacceptprovincekillrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='automakekillhouserequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='automakekillhouserequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='automatickillrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='automatickillrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='automaticstewardallocation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='automaticstewardallocation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='car', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='car', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='checkkillhousecomplaint', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='checkkillhousecomplaint', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='checkstate', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='checkstate', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='checkunusualcasualties', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='checkunusualcasualties', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='citycommerce', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='citycommerce', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityjahad', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityjahad', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityoperator', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityoperator', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityoperatorcheckrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityoperatorcheckrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityvet', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='cityvet', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='coldhouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='coldhouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='coldhouseallocations', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='coldhouseallocations', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='commerce', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='commerce', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='debt', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='debt', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='deposit', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='deposit', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='depositallocation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='depositallocation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='driverrequestcancel', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='driverrequestcancel', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='evacuationpermit', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='evacuationpermit', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='financialdocument', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='financialdocument', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='financialtransaction', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='financialtransaction', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='freesalewithinprovince', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='freesalewithinprovince', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 687431)), + ), + migrations.AlterField( + model_name='functionexecutor', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='functionexecutor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='guildroom', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='guildroom', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='guilds', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='guilds', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='guildswarehouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='guildswarehouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hatchinglossespermission', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hatchinglossespermission', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hourlimit', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='hourlimit', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='inspectoroperator', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='inspectoroperator', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='itransaction', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='itransaction', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='jahad', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='jahad', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseaddcar', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseaddcar', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseallowvet', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseallowvet', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseassignmentimages', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseassignmentimages', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseassignmentinformation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseassignmentinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousecheckrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousecheckrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousecomplaint', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousecomplaint', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousecreditors', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousecreditors', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousedailyquota', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousedailyquota', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousedriver', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousedriver', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefactortopoultry', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefactortopoultry', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefactortoprovince', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefactortoprovince', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefreebarinformation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefreebarinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefreesalebarinformation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousefreesalebarinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousehourlimit', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousehourlimit', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseoperator', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouseoperator', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousepercentage', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousepercentage', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousepercentageoflosses', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousepercentageoflosses', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousepurchaserequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousepurchaserequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestaction', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestaction', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestactionwinner', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestactionwinner', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestexchange', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestexchange', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestexchangeaddcar', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestexchangeaddcar', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestexchangereserve', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhouserequestexchangereserve', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousevet', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousevet', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousewarehouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killhousewarehouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killrequestfactor', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killrequestfactor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killrequestfactorpayment', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='killrequestfactorpayment', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='livestocksupport', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='livestocksupport', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='monthlyprofitpercentage', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='monthlyprofitpercentage', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='mostsearch', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='mostsearch', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='observatory', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='observatory', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='operationlimitation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='operationlimitation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 645696)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 645654)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 645686)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 645673)), + ), + migrations.AlterField( + model_name='paymentdeadline', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='paymentdeadline', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='penalty', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='penalty', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='percentageoflosses', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='percentageoflosses', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poscompany', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poscompany', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='posid', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='posid', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='positem', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='positem', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='posmachine', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='posmachine', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='postransactions', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='postransactions', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='posversion', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='posversion', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultry', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 647089)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 647024)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 647037)), + ), + migrations.AlterField( + model_name='poultry', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryallowcityprovince', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryallowcityprovince', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryassignmentinformation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryassignmentinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryhatching', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryhatching', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequestauction', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequestauction', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequestexchange', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequestexchange', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequestexchangeaccept', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultryrequestexchangeaccept', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultrytenant', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='poultrytenant', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='povinceinspector', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='povinceinspector', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='pricing', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='pricing', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='product', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='product', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhousechoosestewardguilds', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhousechoosestewardguilds', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhousedirectbuying', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhousedirectbuying', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhousedirectbuyingtotal', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhousedirectbuyingtotal', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregistercar', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregistercar', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregisterguilds', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregisterguilds', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregisterguildstotal', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregisterguildstotal', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrychoosekillhouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrychoosekillhouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrychoosekillhousetotal', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrychoosekillhousetotal', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrysellfree', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrysellfree', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrysellfreetotal', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceallowpoultrysellfreetotal', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceautoallocation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceautoallocation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckinformation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckkillhousefactor', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckkillhousefactor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckoperatoroutrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckoperatoroutrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckoperatorrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincecheckoperatorrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincefactortokillhouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincefactortokillhouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincefactortokillhouseforpoultry', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincefactortokillhouseforpoultry', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceimportkillhouseoutfactors', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceimportkillhouseoutfactors', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincekillrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincekillrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceoperator', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provinceoperator', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincepercentleftover', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincepercentleftover', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincerequestaction', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincerequestaction', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincesupervisor', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincesupervisor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincialgovernment', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='provincialgovernment', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='reportingfieldrolelimitation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='reportingfieldrolelimitation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='searchfields', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='searchfields', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='sellforfreezing', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='sellforfreezing', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='shareofallocation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='shareofallocation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='smslicense', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='smslicense', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='steward', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='steward', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='stewardallocation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='stewardallocation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='stewardfreebarinformation', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='stewardfreebarinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='stewardwarehouse', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='stewardwarehouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 13, 52, 21, 652532)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='typeactivity', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='typeactivity', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vet', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vet', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetcheckallocations', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetcheckallocations', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetcheckrequest', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetcheckrequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetfarm', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetfarm', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetfarminspection', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetfarminspection', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetsupervisor', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='vetsupervisor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='wagepayment', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='wagepayment', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='wallet', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='wallet', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='warehousefactor', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='warehousefactor', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/panel/migrations/0102_auto_20240409_1239.py b/panel/migrations/0102_auto_20240409_1239.py new file mode 100644 index 0000000..0fccddd --- /dev/null +++ b/panel/migrations/0102_auto_20240409_1239.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-04-09 12: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', '0101_operationlimitation_vet_check_kill_house_assignment_limitation_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 966798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 900798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 900798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 900798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 900798)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 902798)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 902798)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 902798)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 38, 57, 911801)), + ), + 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, 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)), + ('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/0103_auto_20240413_1450.py b/panel/migrations/0103_auto_20240413_1450.py new file mode 100644 index 0000000..3bb7bbf --- /dev/null +++ b/panel/migrations/0103_auto_20240413_1450.py @@ -0,0 +1,88 @@ +# Generated by Django 3.2.13 on 2024-04-13 14: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', '0102_auto_20240409_1239'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 650861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 603861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 603861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 603861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 603861)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 605861)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 604861)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 605861)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 14, 50, 5, 611861)), + ), + 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, 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_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/0104_auto_20240414_1343.py b/panel/migrations/0104_auto_20240414_1343.py new file mode 100644 index 0000000..7d49699 --- /dev/null +++ b/panel/migrations/0104_auto_20240414_1343.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2024-04-14 13:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0103_auto_20240413_1450'), + ] + + 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.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, 13, 43, 45, 642052)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 557051)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 557051)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 557051)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 557051)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 562052)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 562052)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 562052)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 13, 43, 45, 577048)), + ), + ] diff --git a/panel/migrations/0105_auto_20240416_1516.py b/panel/migrations/0105_auto_20240416_1516.py new file mode 100644 index 0000000..88fd876 --- /dev/null +++ b/panel/migrations/0105_auto_20240416_1516.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2024-04-16 15: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 = [ + ('authentication', '0025_auto_20240416_1516'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0104_auto_20240414_1343'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 502475)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 455516)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 455516)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 455516)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 455516)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 457515)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 457515)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 457515)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 16, 37, 463515)), + ), + 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, 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='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, 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_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/0106_auto_20240417_1456.py b/panel/migrations/0106_auto_20240417_1456.py new file mode 100644 index 0000000..dddd219 --- /dev/null +++ b/panel/migrations/0106_auto_20240417_1456.py @@ -0,0 +1,88 @@ +# Generated by Django 3.2.13 on 2024-04-17 14: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', '0105_auto_20240416_1516'), + ] + + 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, 14, 56, 14, 467960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 283962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 283962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 283962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 283962)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 287956)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 287956)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 287956)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 14, 56, 14, 305960)), + ), + 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, null=True, 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/0107_auto_20240418_1542.py b/panel/migrations/0107_auto_20240418_1542.py new file mode 100644 index 0000000..2f3b304 --- /dev/null +++ b/panel/migrations/0107_auto_20240418_1542.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-04-18 15:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0106_auto_20240417_1456'), + ] + + operations = [ + migrations.AddField( + model_name='announcements', + name='role', + field=models.CharField(max_length=100, null=True), + ), + 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, 42, 4, 811493)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 725489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 725489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 725489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 725489)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 727486)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 727486)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 727486)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 42, 4, 741490)), + ), + ] diff --git a/panel/migrations/0108_auto_20240420_0047.py b/panel/migrations/0108_auto_20240420_0047.py new file mode 100644 index 0000000..951ee3c --- /dev/null +++ b/panel/migrations/0108_auto_20240420_0047.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-04-20 00: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), + ('authentication', '0027_auto_20240420_0047'), + ('panel', '0107_auto_20240418_1542'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 860066)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 800068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 800068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 800068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 800068)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 802068)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 802068)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 802068)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 47, 23, 811068)), + ), + 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, 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='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/0109_auto_20240420_1621.py b/panel/migrations/0109_auto_20240420_1621.py new file mode 100644 index 0000000..704d659 --- /dev/null +++ b/panel/migrations/0109_auto_20240420_1621.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-04-20 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', '0108_auto_20240420_0047'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 980652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 899655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 899655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 899655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 899655)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 902656)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 902656)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 902656)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 16, 21, 41, 912655)), + ), + 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, null=True, 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/0110_auto_20240427_1523.py b/panel/migrations/0110_auto_20240427_1523.py new file mode 100644 index 0000000..b364597 --- /dev/null +++ b/panel/migrations/0110_auto_20240427_1523.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-27 15:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0109_auto_20240420_1621'), + ] + + 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, 15, 23, 23, 137388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 32386)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 31388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 32386)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 32386)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 35391)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 34391)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 34391)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 15, 23, 23, 52389)), + ), + ] diff --git a/panel/migrations/0111_auto_20240429_1320.py b/panel/migrations/0111_auto_20240429_1320.py new file mode 100644 index 0000000..9ac3836 --- /dev/null +++ b/panel/migrations/0111_auto_20240429_1320.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2024-04-29 13:20 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0110_auto_20240427_1523'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='type', + field=models.CharField(default='public', max_length=100), + ), + 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.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, 13, 19, 56, 914748)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 868708)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 868708)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 868708)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 868708)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 870708)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 869708)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 869708)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 13, 19, 56, 876746)), + ), + ] diff --git a/panel/migrations/0112_auto_20240430_1548.py b/panel/migrations/0112_auto_20240430_1548.py new file mode 100644 index 0000000..b175875 --- /dev/null +++ b/panel/migrations/0112_auto_20240430_1548.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-04-30 15:48 + +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', '0111_auto_20240429_1320'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 29, 27654)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 977398)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 977398)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 977398)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 977398)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 979398)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 979398)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 979398)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 15, 48, 28, 986398)), + ), + 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, 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.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(default='pending', max_length=20)), + ('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/0113_auto_20240506_1514.py b/panel/migrations/0113_auto_20240506_1514.py new file mode 100644 index 0000000..dae30f3 --- /dev/null +++ b/panel/migrations/0113_auto_20240506_1514.py @@ -0,0 +1,115 @@ +# Generated by Django 3.2.13 on 2024-05-06 15:14 + +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_20240430_1548'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 120027)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 59028)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 59028)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 59028)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 59028)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 61028)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 61028)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 61028)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 14, 20, 69030)), + ), + 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, 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=500, 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='ShareType', + 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=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, + }, + ), + 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, 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)), + ('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='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/0114_auto_20240507_1538.py b/panel/migrations/0114_auto_20240507_1538.py new file mode 100644 index 0000000..665dbc3 --- /dev/null +++ b/panel/migrations/0114_auto_20240507_1538.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-07 15:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0113_auto_20240506_1514'), + ] + + 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, 15, 37, 57, 307292)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 182291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 182291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 182291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 182291)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 186291)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 186291)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 186291)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 15, 37, 57, 204292)), + ), + ] diff --git a/panel/migrations/0115_auto_20240508_1038.py b/panel/migrations/0115_auto_20240508_1038.py new file mode 100644 index 0000000..127263b --- /dev/null +++ b/panel/migrations/0115_auto_20240508_1038.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-08 10:38 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0114_auto_20240507_1538'), + ] + + 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, 37, 37, 856984)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 808953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 808953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 808953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 808953)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 810948)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 810948)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 810948)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 37, 37, 816948)), + ), + ] diff --git a/panel/migrations/0116_auto_20240508_1355.py b/panel/migrations/0116_auto_20240508_1355.py new file mode 100644 index 0000000..2f2d703 --- /dev/null +++ b/panel/migrations/0116_auto_20240508_1355.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-05-08 13:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0115_auto_20240508_1038'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='buy_type', + field=models.CharField(max_length=50, null=True), + ), + 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.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, 8, 13, 54, 57, 591309)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 500310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 500310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 500310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 500310)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 505310)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 505310)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 505310)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 13, 54, 57, 519312)), + ), + ] diff --git a/panel/migrations/0117_auto_20240513_1607.py b/panel/migrations/0117_auto_20240513_1607.py new file mode 100644 index 0000000..f006799 --- /dev/null +++ b/panel/migrations/0117_auto_20240513_1607.py @@ -0,0 +1,130 @@ +# Generated by Django 3.2.13 on 2024-05-13 16: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', '0029_auto_20240513_1607'), + ('panel', '0116_auto_20240508_1355'), + ] + + 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, 13, 16, 6, 57, 417394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 761389)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 761389)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 761389)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 761389)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 767388)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 767388)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 56, 767388)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 16, 6, 57, 145393)), + ), + 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, 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)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_address', to='authentication.systemaddress')), + ('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')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + 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, 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)), + ('state', models.CharField(default='pending', max_length=50)), + ('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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0118_auto_20240515_1335.py b/panel/migrations/0118_auto_20240515_1335.py new file mode 100644 index 0000000..3f3924c --- /dev/null +++ b/panel/migrations/0118_auto_20240515_1335.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-05-15 13:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0117_auto_20240513_1607'), + ] + + 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='quarantine_code_registrar', + field=models.JSONField(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, 13, 35, 20, 596704)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 548699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 547698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 548699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 547698)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 550700)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 550700)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 550700)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 35, 20, 557701)), + ), + ] diff --git a/panel/migrations/0119_auto_20240516_1515.py b/panel/migrations/0119_auto_20240516_1515.py new file mode 100644 index 0000000..e8d9185 --- /dev/null +++ b/panel/migrations/0119_auto_20240516_1515.py @@ -0,0 +1,297 @@ +# Generated by Django 3.2.13 on 2024-05-16 15: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', '0118_auto_20240515_1335'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='other_share_percent', + field=models.FloatField(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='union_share_percent', + field=models.FloatField(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='chainallocation', + name='wallet_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='other_share_percent', + field=models.FloatField(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='union_share_percent', + field=models.FloatField(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.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', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='other_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='total_wage_amount', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='union_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='wallet_share', + field=models.BigIntegerField(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.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, 16, 15, 15, 11, 591198)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 542159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 542159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 542159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 542159)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 545159)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 545159)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 545159)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 15, 15, 11, 552158)), + ), + 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, 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_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, + }, + ), + 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, 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.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/0120_auto_20240518_0955.py b/panel/migrations/0120_auto_20240518_0955.py new file mode 100644 index 0000000..21291ab --- /dev/null +++ b/panel/migrations/0120_auto_20240518_0955.py @@ -0,0 +1,209 @@ +# Generated by Django 3.2.13 on 2024-05-18 09: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', '0119_auto_20240516_1515'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompanytransaction', + name='cardHolderPan', + field=models.CharField(max_length=100, null=True), + ), + 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='orderId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='other_share', + field=models.BigIntegerField(default=0), + ), + 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='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='cardHolderPan', + field=models.CharField(max_length=100, null=True), + ), + 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='orderId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='other_share', + field=models.BigIntegerField(default=0), + ), + 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.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, 18, 9, 55, 24, 218161)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 167877)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 167877)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 167877)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 167877)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 170876)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 170876)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 170876)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 18, 9, 55, 24, 178878)), + ), + 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, 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)), + ('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/0121_auto_20240521_1101.py b/panel/migrations/0121_auto_20240521_1101.py new file mode 100644 index 0000000..89cd062 --- /dev/null +++ b/panel/migrations/0121_auto_20240521_1101.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-05-21 11:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0120_auto_20240518_0955'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='archive_wage', + field=models.BooleanField(default=False), + ), + 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, 11, 1, 8, 392337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 343337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 343337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 343337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 343337)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 347344)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 347344)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 347344)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 11, 1, 8, 354337)), + ), + ] diff --git a/panel/migrations/0122_auto_20240523_1606.py b/panel/migrations/0122_auto_20240523_1606.py new file mode 100644 index 0000000..4195661 --- /dev/null +++ b/panel/migrations/0122_auto_20240523_1606.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-23 16:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0121_auto_20240521_1101'), + ] + + 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, 5, 57, 694608)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 559610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 559610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 559610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 559610)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 565617)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 565617)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 565617)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 5, 57, 581614)), + ), + ] diff --git a/panel/migrations/0123_auto_20240525_1509.py b/panel/migrations/0123_auto_20240525_1509.py new file mode 100644 index 0000000..46fdbe6 --- /dev/null +++ b/panel/migrations/0123_auto_20240525_1509.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-25 15:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0122_auto_20240523_1606'), + ] + + 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, 15, 9, 5, 1437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 748088)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 748088)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 748088)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 748088)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 754085)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 754085)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 754085)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 15, 9, 4, 781442)), + ), + ] diff --git a/panel/migrations/0124_auto_20240528_1328.py b/panel/migrations/0124_auto_20240528_1328.py new file mode 100644 index 0000000..0a34a73 --- /dev/null +++ b/panel/migrations/0124_auto_20240528_1328.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-28 13:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0123_auto_20240525_1509'), + ] + + 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, 13, 28, 52, 856147)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 808147)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 808147)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 808147)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 808147)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 811147)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 811147)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 811147)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 13, 28, 52, 818147)), + ), + ] diff --git a/panel/migrations/0125_auto_20240605_1321.py b/panel/migrations/0125_auto_20240605_1321.py new file mode 100644 index 0000000..0274429 --- /dev/null +++ b/panel/migrations/0125_auto_20240605_1321.py @@ -0,0 +1,190 @@ +# Generated by Django 3.2.13 on 2024-06-05 13:21 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0124_auto_20240528_1328'), + ] + + 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.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='wage_pay', + field=models.BooleanField(default=False), + ), + 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, 13, 21, 46, 448862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 373655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 373655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 373655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 373655)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 378654)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 378654)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 378654)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 13, 21, 46, 386618)), + ), + ] diff --git a/panel/migrations/0126_auto_20240605_1903.py b/panel/migrations/0126_auto_20240605_1903.py new file mode 100644 index 0000000..091786e --- /dev/null +++ b/panel/migrations/0126_auto_20240605_1903.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-05 19:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0125_auto_20240605_1321'), + ] + + 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, 19, 3, 16, 36427)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 987261)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 987261)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 987261)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 987261)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 990261)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 990261)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 990261)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 19, 3, 15, 996261)), + ), + ] diff --git a/panel/migrations/0127_auto_20240606_1500.py b/panel/migrations/0127_auto_20240606_1500.py new file mode 100644 index 0000000..0790025 --- /dev/null +++ b/panel/migrations/0127_auto_20240606_1500.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-06-06 15:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0126_auto_20240605_1903'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='index_weight', + field=models.FloatField(default=0), + ), + 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, 15, 0, 19, 894606)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 845642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 845642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 845642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 845642)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 848643)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 848643)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 848643)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 15, 0, 19, 854642)), + ), + ] diff --git a/panel/migrations/0128_auto_20240609_2150.py b/panel/migrations/0128_auto_20240609_2150.py new file mode 100644 index 0000000..292a93c --- /dev/null +++ b/panel/migrations/0128_auto_20240609_2150.py @@ -0,0 +1,102 @@ +# Generated by Django 3.2.13 on 2024-06-09 21: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', '0127_auto_20240606_1500'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='health_code', + field=models.CharField(max_length=100, null=True), + ), + 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, 9, 21, 50, 30, 119862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 69862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 69862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 69862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 69862)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 72862)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 72862)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 72862)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 9, 21, 50, 30, 79862)), + ), + 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, null=True, 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/0129_auto_20240612_1623.py b/panel/migrations/0129_auto_20240612_1623.py new file mode 100644 index 0000000..ee08598 --- /dev/null +++ b/panel/migrations/0129_auto_20240612_1623.py @@ -0,0 +1,101 @@ +# Generated by Django 3.2.13 on 2024-06-12 16: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', '0128_auto_20240609_2150'), + ] + + 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, 16, 23, 10, 822558)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 514556)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 514556)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 514556)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 514556)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 522557)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 522557)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 522557)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 16, 23, 10, 574558)), + ), + 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, 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)), + ('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/0130_auto_20240620_1609.py b/panel/migrations/0130_auto_20240620_1609.py new file mode 100644 index 0000000..2d07c57 --- /dev/null +++ b/panel/migrations/0130_auto_20240620_1609.py @@ -0,0 +1,227 @@ +# Generated by Django 3.2.13 on 2024-06-20 16: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 = [ + ('authentication', '0033_auto_20240620_1609'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0129_auto_20240612_1623'), + ] + + 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.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.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.AddField( + model_name='poultryrequest', + name='agent', + field=models.JSONField(null=True), + ), + 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_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='buyer_province', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='has_wage', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='hatching_left_over', + field=models.IntegerField(default=0), + ), + 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, 20, 16, 8, 52, 933405)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 868411)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 867409)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 868411)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 867409)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 872412)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 872412)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 872412)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 16, 8, 52, 881410)), + ), + 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, 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)), + ('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='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)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='out_province_poultry_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + 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, 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='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, + }, + ), + 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, 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_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, + }, + ), + 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.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'), + ), + ] diff --git a/panel/migrations/0131_auto_20240622_1529.py b/panel/migrations/0131_auto_20240622_1529.py new file mode 100644 index 0000000..ddbabc3 --- /dev/null +++ b/panel/migrations/0131_auto_20240622_1529.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-06-22 15:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0130_auto_20240620_1609'), + ] + + operations = [ + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='kill_house_unique_id', + field=models.CharField(max_length=100, null=True), + ), + 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, 15, 29, 8, 547394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 218400)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 218400)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 218400)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 218400)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 289401)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 288399)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 288399)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 15, 29, 8, 320400)), + ), + ] diff --git a/panel/migrations/0132_auto_20240623_1242.py b/panel/migrations/0132_auto_20240623_1242.py new file mode 100644 index 0000000..71cdd42 --- /dev/null +++ b/panel/migrations/0132_auto_20240623_1242.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-23 12:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0131_auto_20240622_1529'), + ] + + 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, 23, 12, 42, 9, 446943)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 394944)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 393944)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 393944)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 393944)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 397944)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 397944)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 397944)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 23, 12, 42, 9, 404944)), + ), + ] diff --git a/panel/migrations/0133_auto_20240626_1705.py b/panel/migrations/0133_auto_20240626_1705.py new file mode 100644 index 0000000..aeb037a --- /dev/null +++ b/panel/migrations/0133_auto_20240626_1705.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-26 17:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0132_auto_20240623_1242'), + ] + + 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, 26, 17, 5, 22, 566599)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 407598)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 407598)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 407598)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 407598)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 417598)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 417598)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 417598)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 26, 17, 5, 22, 437599)), + ), + ] diff --git a/panel/migrations/0134_auto_20240629_1542.py b/panel/migrations/0134_auto_20240629_1542.py new file mode 100644 index 0000000..634157b --- /dev/null +++ b/panel/migrations/0134_auto_20240629_1542.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2024-06-29 15: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', '0133_auto_20240626_1705'), + ] + + 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, 15, 42, 27, 925276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 874276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 874276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 874276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 874276)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 877276)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 877276)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 877276)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 15, 42, 27, 884275)), + ), + 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, 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=500, null=True)), + ('sms', models.BooleanField(default=False)), + ('is_error', 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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0135_auto_20240630_1545.py b/panel/migrations/0135_auto_20240630_1545.py new file mode 100644 index 0000000..ad25511 --- /dev/null +++ b/panel/migrations/0135_auto_20240630_1545.py @@ -0,0 +1,135 @@ +# Generated by Django 3.2.13 on 2024-06-30 15: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', '0134_auto_20240629_1542'), + ] + + 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, 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=500, null=True)), + ('active', models.BooleanField(default=False)), + ('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, 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)), + ('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=500, 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, 15, 45, 16, 152335)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 101336)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 101336)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 101336)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 101336)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 104336)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 104336)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 104336)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 15, 45, 16, 111335)), + ), + 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, 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)), + ('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, + }, + ), + 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, 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)), + ('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/0136_auto_20240701_1548.py b/panel/migrations/0136_auto_20240701_1548.py new file mode 100644 index 0000000..7652dc2 --- /dev/null +++ b/panel/migrations/0136_auto_20240701_1548.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-01 15:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0135_auto_20240630_1545'), + ] + + 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, 48, 35, 589675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 502684)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 502684)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 502684)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 502684)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 507685)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 507685)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 507685)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 48, 35, 523679)), + ), + ] diff --git a/panel/migrations/0137_auto_20240702_1601.py b/panel/migrations/0137_auto_20240702_1601.py new file mode 100644 index 0000000..cb06796 --- /dev/null +++ b/panel/migrations/0137_auto_20240702_1601.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2024-07-02 16: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', '0136_auto_20240701_1548'), + ] + + operations = [ + migrations.RemoveField( + model_name='reportsusers', + name='post', + ), + 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, 16, 1, 33, 299788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 247785)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 247785)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 247785)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 247785)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 251788)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 251788)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 251788)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 16, 1, 33, 258788)), + ), + 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, 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=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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0138_auto_20240703_1546.py b/panel/migrations/0138_auto_20240703_1546.py new file mode 100644 index 0000000..3e89abf --- /dev/null +++ b/panel/migrations/0138_auto_20240703_1546.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2024-07-03 15:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0137_auto_20240702_1601'), + ] + + operations = [ + migrations.RemoveField( + model_name='reportsusers', + name='user_position', + ), + migrations.AddField( + model_name='internaltransaction', + name='description', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='reports', + name='description', + field=models.TextField(null=True), + ), + 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.AddField( + model_name='reportsusers', + name='position', + field=models.CharField(max_length=100, null=True), + ), + 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, 15, 45, 55, 869259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 818259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 818259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 818259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 818259)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 822259)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 821259)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 822259)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 45, 55, 829259)), + ), + migrations.DeleteModel( + name='UserPosition', + ), + ] diff --git a/panel/migrations/0139_auto_20240706_1536.py b/panel/migrations/0139_auto_20240706_1536.py new file mode 100644 index 0000000..6b73d2e --- /dev/null +++ b/panel/migrations/0139_auto_20240706_1536.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-07-06 15:36 + +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', '0138_auto_20240703_1546'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 309762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 258764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 258764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 258764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 258764)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 262764)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 262764)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 262764)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 36, 2, 269764)), + ), + 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, null=True, 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)), + ('active', models.BooleanField(default=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/0140_auto_20240707_1529.py b/panel/migrations/0140_auto_20240707_1529.py new file mode 100644 index 0000000..10e8921 --- /dev/null +++ b/panel/migrations/0140_auto_20240707_1529.py @@ -0,0 +1,117 @@ +# Generated by Django 3.2.13 on 2024-07-07 15: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 = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0139_auto_20240706_1536'), + ] + + 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, null=True, 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, 7, 15, 29, 44, 475341)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 420373)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 420373)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 420373)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 420373)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 423376)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 423376)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 423376)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 15, 29, 44, 431374)), + ), + 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, 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='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, 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='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/0141_auto_20240713_0930.py b/panel/migrations/0141_auto_20240713_0930.py new file mode 100644 index 0000000..81792ac --- /dev/null +++ b/panel/migrations/0141_auto_20240713_0930.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2024-07-13 09:30 + +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', '0140_auto_20240707_1529'), + ] + + 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, 13, 9, 30, 4, 290861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 239849)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 239849)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 239849)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 239849)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 242853)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 242853)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 242853)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 30, 4, 250852)), + ), + 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, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('product_id', models.IntegerField(default=0)), + ('name', models.CharField(max_length=200, 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.FloatField(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)), + ('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/0142_auto_20240713_1405.py b/panel/migrations/0142_auto_20240713_1405.py new file mode 100644 index 0000000..7e48fe4 --- /dev/null +++ b/panel/migrations/0142_auto_20240713_1405.py @@ -0,0 +1,112 @@ +# Generated by Django 3.2.13 on 2024-07-13 14: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', '0141_auto_20240713_0930'), + ] + + 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, 14, 4, 21, 906669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 200671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 200671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 200671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 200671)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 250674)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 250674)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 250674)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 4, 20, 273674)), + ), + 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, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('union_account', models.CharField(max_length=50, null=True)), + ('company_account', models.CharField(max_length=50, null=True)), + ('guild_account', models.CharField(max_length=50, null=True)), + ('other_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/0143_auto_20240713_1433.py b/panel/migrations/0143_auto_20240713_1433.py new file mode 100644 index 0000000..4e059e7 --- /dev/null +++ b/panel/migrations/0143_auto_20240713_1433.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2024-07-13 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0142_auto_20240713_1405'), + ] + + 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, 14, 32, 51, 819264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 750300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 750300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 750300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 750300)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 757300)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 757300)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 757300)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 14, 32, 51, 765304)), + ), + ] diff --git a/panel/migrations/0144_auto_20240713_1535.py b/panel/migrations/0144_auto_20240713_1535.py new file mode 100644 index 0000000..1d19972 --- /dev/null +++ b/panel/migrations/0144_auto_20240713_1535.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2024-07-13 15:35 + +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', '0034_auto_20240713_1535'), + ('panel', '0143_auto_20240713_1433'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 453846)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 388848)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 388848)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 388848)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 388848)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 392846)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 391847)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 391847)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 35, 11, 404844)), + ), + 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, 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='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, + }, + ), + 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, 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='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/0145_auto_20240720_1456.py b/panel/migrations/0145_auto_20240720_1456.py new file mode 100644 index 0000000..ad71fae --- /dev/null +++ b/panel/migrations/0145_auto_20240720_1456.py @@ -0,0 +1,159 @@ +# Generated by Django 3.2.13 on 2024-07-20 14: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', '0144_auto_20240713_1535'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='accept_reject_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='export_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='export_country', + field=models.CharField(max_length=100, 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='export_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='input_export_code', + field=models.CharField(max_length=20, null=True), + ), + 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.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, 20, 14, 56, 21, 702867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 650866)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 650866)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 650866)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 650866)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 653866)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 653866)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 653866)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 14, 56, 21, 661866)), + ), + 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, 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)), + ('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, + }, + ), + 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, 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)), + ('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='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/0146_auto_20240724_1518.py b/panel/migrations/0146_auto_20240724_1518.py new file mode 100644 index 0000000..c842c3e --- /dev/null +++ b/panel/migrations/0146_auto_20240724_1518.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-24 15:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0145_auto_20240720_1456'), + ] + + 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, 15, 17, 57, 960296)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 902748)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 902748)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 902748)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 902748)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 906746)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 906746)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 906746)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 15, 17, 57, 912749)), + ), + ] diff --git a/panel/migrations/0147_auto_20240725_1447.py b/panel/migrations/0147_auto_20240725_1447.py new file mode 100644 index 0000000..10d6ee4 --- /dev/null +++ b/panel/migrations/0147_auto_20240725_1447.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-07-25 14:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0146_auto_20240724_1518'), + ] + + 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.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, 14, 46, 47, 321915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 177829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 177829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 177829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 177829)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 187823)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 187823)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 187823)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 14, 46, 47, 207846)), + ), + ] diff --git a/panel/migrations/0148_auto_20240727_1139.py b/panel/migrations/0148_auto_20240727_1139.py new file mode 100644 index 0000000..00cd036 --- /dev/null +++ b/panel/migrations/0148_auto_20240727_1139.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-27 11:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0147_auto_20240725_1447'), + ] + + 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, 11, 38, 35, 202100)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 112032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 112032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 112032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 112032)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 118031)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 118031)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 118031)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 11, 38, 35, 130100)), + ), + ] diff --git a/panel/migrations/0149_auto_20240803_1454.py b/panel/migrations/0149_auto_20240803_1454.py new file mode 100644 index 0000000..7f5eb4a --- /dev/null +++ b/panel/migrations/0149_auto_20240803_1454.py @@ -0,0 +1,115 @@ +# Generated by Django 3.2.13 on 2024-08-03 14: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 = [ + ('authentication', '0035_auto_20240803_1454'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0148_auto_20240727_1139'), + ] + + 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.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, 3, 14, 53, 59, 595675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 544713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 544713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 544713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 544713)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 547711)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 547711)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 547711)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 14, 53, 59, 554712)), + ), + 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, null=True, 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)), + ('limitation_amount', models.FloatField(default=0)), + ('car', models.CharField(max_length=100, null=True)), + ('pelak', models.CharField(max_length=100, null=True)), + ('active', models.BooleanField(default=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)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_guild', to='panel.guilds')), + ('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)), + ('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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0150_auto_20240804_1413.py b/panel/migrations/0150_auto_20240804_1413.py new file mode 100644 index 0000000..c4e1034 --- /dev/null +++ b/panel/migrations/0150_auto_20240804_1413.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-08-04 14:13 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0149_auto_20240803_1454'), + ] + + operations = [ + migrations.AddField( + model_name='dispenser', + name='registrar', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='has_pos', + field=models.BooleanField(default=False), + ), + 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, 12, 36, 553437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 293960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 293960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 293960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 293960)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 302975)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 302975)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 302975)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 12, 36, 322976)), + ), + ] diff --git a/panel/migrations/0151_auto_20240805_1422.py b/panel/migrations/0151_auto_20240805_1422.py new file mode 100644 index 0000000..c243200 --- /dev/null +++ b/panel/migrations/0151_auto_20240805_1422.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-08-05 14:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0150_auto_20240804_1413'), + ] + + operations = [ + migrations.AddField( + model_name='dispenser', + name='free_guilds', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='dispenser', + name='free_sale', + field=models.BooleanField(default=False), + ), + migrations.AddField( + 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, 5, 14, 21, 49, 145967)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 62959)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 62959)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 62959)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 62959)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 67960)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 67960)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 67960)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 5, 14, 21, 49, 78959)), + ), + ] diff --git a/panel/migrations/0152_auto_20240807_1448.py b/panel/migrations/0152_auto_20240807_1448.py new file mode 100644 index 0000000..cfef7bf --- /dev/null +++ b/panel/migrations/0152_auto_20240807_1448.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-07 14:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0151_auto_20240805_1422'), + ] + + 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, 7, 14, 48, 35, 507927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 154607)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 154607)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 154607)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 154607)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 161121)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 161121)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 161121)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 7, 14, 48, 35, 194122)), + ), + ] diff --git a/panel/migrations/0153_auto_20240808_1331.py b/panel/migrations/0153_auto_20240808_1331.py new file mode 100644 index 0000000..4bce177 --- /dev/null +++ b/panel/migrations/0153_auto_20240808_1331.py @@ -0,0 +1,107 @@ +# Generated by Django 3.2.13 on 2024-08-08 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', '0152_auto_20240807_1448'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 39, 35496)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 922500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 922500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 922500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 922500)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 942503)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 942503)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 942503)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 13, 30, 38, 957494)), + ), + 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, 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='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='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='stewardallocation', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_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'), + ), + ] diff --git a/panel/migrations/0154_auto_20240810_1440.py b/panel/migrations/0154_auto_20240810_1440.py new file mode 100644 index 0000000..9d14e54 --- /dev/null +++ b/panel/migrations/0154_auto_20240810_1440.py @@ -0,0 +1,269 @@ +# Generated by Django 3.2.13 on 2024-08-10 14:40 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0153_auto_20240808_1331'), + ] + + operations = [ + migrations.RemoveField( + model_name='rolesproducts', + name='active', + ), + 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='poscompany', + name='en_name', + field=models.CharField(max_length=100, null=True), + ), + 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_quantity_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_weight_from', + 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.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, 14, 39, 48, 746107)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 623587)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 622588)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 623587)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 623587)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 632109)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 632109)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 632109)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 14, 39, 48, 649106)), + ), + ] diff --git a/panel/migrations/0155_auto_20240813_1029.py b/panel/migrations/0155_auto_20240813_1029.py new file mode 100644 index 0000000..bd890bd --- /dev/null +++ b/panel/migrations/0155_auto_20240813_1029.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-08-13 10:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0154_auto_20240810_1440'), + ] + + 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, 10, 29, 19, 353461)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 279465)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 279465)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 279465)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 279465)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 284467)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 284467)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 284467)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 10, 29, 19, 294465)), + ), + ] diff --git a/panel/migrations/0156_auto_20240819_1458.py b/panel/migrations/0156_auto_20240819_1458.py new file mode 100644 index 0000000..54446a5 --- /dev/null +++ b/panel/migrations/0156_auto_20240819_1458.py @@ -0,0 +1,121 @@ +# Generated by Django 3.2.13 on 2024-08-19 14:58 + +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', '0155_auto_20240813_1029'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='extra_bar_kill_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='off', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_kill_capacity', + field=models.FloatField(default=0), + ), + 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, 19, 14, 57, 58, 536107)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 118558)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 118558)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 118558)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 118558)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 124560)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 124560)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 124560)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 14, 57, 58, 138559)), + ), + 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, 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)), + ('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, + }, + ), + 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, null=True, 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/0157_auto_20240820_1051.py b/panel/migrations/0157_auto_20240820_1051.py new file mode 100644 index 0000000..c16dd70 --- /dev/null +++ b/panel/migrations/0157_auto_20240820_1051.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-08-20 10: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', '0036_auto_20240820_1051'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0156_auto_20240819_1458'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 45, 31393)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 962392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 962392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 962392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 962392)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 967389)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 967389)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 967389)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 51, 44, 977393)), + ), + 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, 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='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/0158_auto_20240821_1445.py b/panel/migrations/0158_auto_20240821_1445.py new file mode 100644 index 0000000..4c0a025 --- /dev/null +++ b/panel/migrations/0158_auto_20240821_1445.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-21 14:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0157_auto_20240820_1051'), + ] + + 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, 14, 44, 50, 961189)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 735053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 735053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 735053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 735053)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 746111)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 746111)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 746111)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 14, 44, 50, 782186)), + ), + ] diff --git a/panel/migrations/0159_auto_20240826_1453.py b/panel/migrations/0159_auto_20240826_1453.py new file mode 100644 index 0000000..a13311f --- /dev/null +++ b/panel/migrations/0159_auto_20240826_1453.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-08-26 14:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0158_auto_20240821_1445'), + ] + + 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, 14, 52, 52, 744469)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 95020)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 95020)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 95020)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 95020)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 104043)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 104043)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 104043)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 14, 52, 52, 313820)), + ), + ] diff --git a/panel/migrations/0160_auto_20240829_1344.py b/panel/migrations/0160_auto_20240829_1344.py new file mode 100644 index 0000000..4a40566 --- /dev/null +++ b/panel/migrations/0160_auto_20240829_1344.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-08-29 13:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0159_auto_20240826_1453'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 545037)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 53398)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 52400)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 53398)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 52400)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 59397)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 58392)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 58392)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 13, 44, 30, 79394)), + ), + ] diff --git a/panel/migrations/0161_auto_20240831_0932.py b/panel/migrations/0161_auto_20240831_0932.py new file mode 100644 index 0000000..287ded5 --- /dev/null +++ b/panel/migrations/0161_auto_20240831_0932.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-08-31 09:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0160_auto_20240829_1344'), + ] + + 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, 31, 53, 644192)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 530181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 530181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 530181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 530181)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 537176)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 536177)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 536177)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 31, 53, 547178)), + ), + ] diff --git a/panel/migrations/0162_auto_20240912_1203.py b/panel/migrations/0162_auto_20240912_1203.py new file mode 100644 index 0000000..4d0b893 --- /dev/null +++ b/panel/migrations/0162_auto_20240912_1203.py @@ -0,0 +1,124 @@ +# Generated by Django 3.2.13 on 2024-09-12 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', '0161_auto_20240831_0932'), + ] + + operations = [ + 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(default='pending', max_length=100), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 16, 85575)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 856578)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 855577)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 856578)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 856578)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 864576)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 864576)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 864576)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 3, 15, 884575)), + ), + 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, 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=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='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)), + ], + options={ + 'abstract': False, + }, + ), + 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, 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)), + ('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, + }, + ), + 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'), + ), + ] diff --git a/panel/migrations/0163_auto_20241014_0957.py b/panel/migrations/0163_auto_20241014_0957.py new file mode 100644 index 0000000..360bf3f --- /dev/null +++ b/panel/migrations/0163_auto_20241014_0957.py @@ -0,0 +1,154 @@ +# Generated by Django 3.2.13 on 2024-10-14 09:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0162_auto_20240912_1203'), + ] + + 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='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='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.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, 14, 9, 57, 23, 687250)), + ), + 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, 10, 14, 9, 57, 23, 625206)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 624206)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 624206)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 624206)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 629203)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 629203)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 629203)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 14, 9, 57, 23, 637198)), + ), + ] diff --git a/panel/migrations/0164_auto_20241016_1031.py b/panel/migrations/0164_auto_20241016_1031.py new file mode 100644 index 0000000..3f491b7 --- /dev/null +++ b/panel/migrations/0164_auto_20241016_1031.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-10-16 10:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0163_auto_20241014_0957'), + ] + + 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, 16, 10, 31, 17, 65791)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 953339)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 953339)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 953339)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 953339)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 964333)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 964333)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 964333)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 10, 31, 16, 977327)), + ), + ] diff --git a/panel/migrations/0165_auto_20241016_1111.py b/panel/migrations/0165_auto_20241016_1111.py new file mode 100644 index 0000000..f6033b6 --- /dev/null +++ b/panel/migrations/0165_auto_20241016_1111.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-16 11:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0164_auto_20241016_1031'), + ] + + 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, 16, 11, 10, 49, 447966)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 497369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 497369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 497369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 497369)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 506364)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 506364)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 506364)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 16, 11, 10, 48, 647312)), + ), + ] diff --git a/panel/migrations/0166_auto_20241017_1246.py b/panel/migrations/0166_auto_20241017_1246.py new file mode 100644 index 0000000..484982f --- /dev/null +++ b/panel/migrations/0166_auto_20241017_1246.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-17 12:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0165_auto_20241016_1111'), + ] + + 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, 46, 1, 829337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 688388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 688388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 688388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 688388)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 698383)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 698383)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 698383)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 46, 1, 719886)), + ), + ] diff --git a/panel/migrations/0167_auto_20241022_1158.py b/panel/migrations/0167_auto_20241022_1158.py new file mode 100644 index 0000000..727d240 --- /dev/null +++ b/panel/migrations/0167_auto_20241022_1158.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-10-22 11:58 + +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', '0166_auto_20241017_1246'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 157071)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 93242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 93242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 93242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 93242)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 96234)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 96234)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 96234)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 11, 58, 33, 110197)), + ), + 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, 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='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/0168_auto_20241022_1200.py b/panel/migrations/0168_auto_20241022_1200.py new file mode 100644 index 0000000..43a07ae --- /dev/null +++ b/panel/migrations/0168_auto_20241022_1200.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-22 12:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0167_auto_20241022_1158'), + ] + + 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, 12, 0, 7, 544243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 491385)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 491385)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 491385)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 491385)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 494377)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 494377)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 494377)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 12, 0, 7, 502355)), + ), + ] diff --git a/panel/migrations/0169_auto_20241023_1331.py b/panel/migrations/0169_auto_20241023_1331.py new file mode 100644 index 0000000..21a31f5 --- /dev/null +++ b/panel/migrations/0169_auto_20241023_1331.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-10-23 13:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0168_auto_20241022_1200'), + ] + + 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.AddField( + model_name='poultryhatching', + name='total_losses', + field=models.BigIntegerField(default=0), + ), + 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, 10, 23, 13, 31, 0, 594399)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 546307)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 31, 0, 562272)), + ), + ] diff --git a/panel/migrations/0170_auto_20241024_0937.py b/panel/migrations/0170_auto_20241024_0937.py new file mode 100644 index 0000000..e1c1816 --- /dev/null +++ b/panel/migrations/0170_auto_20241024_0937.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-24 09:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0169_auto_20241023_1331'), + ] + + 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, 37, 39, 211637)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 167106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 167106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 167106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 167106)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 170582)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 170582)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 170582)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 37, 39, 179919)), + ), + ] diff --git a/panel/migrations/0171_auto_20241026_0958.py b/panel/migrations/0171_auto_20241026_0958.py new file mode 100644 index 0000000..5a4ef70 --- /dev/null +++ b/panel/migrations/0171_auto_20241026_0958.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-10-26 09:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0170_auto_20241024_0937'), + ] + + 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, 58, 23, 432023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 384828)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 384828)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 384828)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 384828)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 388305)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 388305)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 388305)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 58, 23, 396998)), + ), + ] diff --git a/panel/migrations/0172_auto_20241026_1356.py b/panel/migrations/0172_auto_20241026_1356.py new file mode 100644 index 0000000..2d6494d --- /dev/null +++ b/panel/migrations/0172_auto_20241026_1356.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-26 13:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0171_auto_20241026_0958'), + ] + + 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, 56, 25, 186752)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 111542)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 56, 25, 127385)), + ), + ] diff --git a/panel/migrations/0173_auto_20241031_1409.py b/panel/migrations/0173_auto_20241031_1409.py new file mode 100644 index 0000000..3a8ee21 --- /dev/null +++ b/panel/migrations/0173_auto_20241031_1409.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2024-10-31 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 = [ + ('authentication', '0037_auto_20241031_1409'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0172_auto_20241026_1356'), + ] + + 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, 10, 31, 14, 9, 6, 583274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 535323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 535323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 535323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 535323)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 538070)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 538070)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 538070)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 31, 14, 9, 6, 546762)), + ), + 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, 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=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/0174_auto_20241103_0818.py b/panel/migrations/0174_auto_20241103_0818.py new file mode 100644 index 0000000..98374c7 --- /dev/null +++ b/panel/migrations/0174_auto_20241103_0818.py @@ -0,0 +1,78 @@ +# Generated by Django 3.2.13 on 2024-11-03 08:18 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0173_auto_20241031_1409'), + ] + + 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=250)), + ('slug', models.CharField(max_length=250)), + ('tel_prefix', models.CharField(max_length=3, null=True)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 312800)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 260215)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 260215)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 260215)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 260215)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 265456)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 265456)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 265456)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 8, 18, 3, 265456)), + ), + migrations.CreateModel( + name='IranCities', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=250)), + ('slug', models.CharField(max_length=250)), + ('province_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='panel.iranprovinces')), + ], + ), + ] diff --git a/panel/migrations/0175_auto_20241103_1105.py b/panel/migrations/0175_auto_20241103_1105.py new file mode 100644 index 0000000..2d5c94e --- /dev/null +++ b/panel/migrations/0175_auto_20241103_1105.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-03 11:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0174_auto_20241103_0818'), + ] + + 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, 11, 5, 48, 620478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 558642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 558642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 558642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 558642)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 562632)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 562632)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 562632)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 5, 48, 571608)), + ), + ] diff --git a/panel/migrations/0176_auto_20241103_1110.py b/panel/migrations/0176_auto_20241103_1110.py new file mode 100644 index 0000000..21a83c7 --- /dev/null +++ b/panel/migrations/0176_auto_20241103_1110.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-03 11:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0175_auto_20241103_1105'), + ] + + 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, 11, 10, 21, 215122)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 162694)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 161696)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 162694)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 162694)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 165685)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 165685)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 165685)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 10, 21, 174111)), + ), + ] diff --git a/panel/migrations/0177_auto_20241103_1114.py b/panel/migrations/0177_auto_20241103_1114.py new file mode 100644 index 0000000..1d51781 --- /dev/null +++ b/panel/migrations/0177_auto_20241103_1114.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-03 11:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0176_auto_20241103_1110'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation_image', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 761861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 709912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 709912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 709912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 709912)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 714043)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 714043)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 714043)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 14, 37, 721272)), + ), + ] diff --git a/panel/migrations/0178_auto_20241103_1120.py b/panel/migrations/0178_auto_20241103_1120.py new file mode 100644 index 0000000..0182782 --- /dev/null +++ b/panel/migrations/0178_auto_20241103_1120.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-03 11:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0177_auto_20241103_1114'), + ] + + 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, 11, 20, 15, 107781)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 35973)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 35973)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 35973)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 35973)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 40959)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 40959)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 40959)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 11, 20, 15, 49935)), + ), + ] diff --git a/panel/migrations/0179_auto_20241109_1604.py b/panel/migrations/0179_auto_20241109_1604.py new file mode 100644 index 0000000..ae2a78d --- /dev/null +++ b/panel/migrations/0179_auto_20241109_1604.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-11-09 16:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0178_auto_20241103_1120'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompany', + name='city', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='chaincompany', + name='postal_code', + 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='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, 16, 3, 54, 760521)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 712821)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 16, 3, 54, 728884)), + ), + ] diff --git a/panel/migrations/0180_auto_20241109_2044.py b/panel/migrations/0180_auto_20241109_2044.py new file mode 100644 index 0000000..c6304cd --- /dev/null +++ b/panel/migrations/0180_auto_20241109_2044.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-09 20:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0179_auto_20241109_1604'), + ] + + 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, 44, 19, 697123)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 624601)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 624601)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 624601)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 624601)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 628600)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 628600)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 628600)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 44, 19, 638606)), + ), + ] diff --git a/panel/migrations/0181_auto_20241109_2158.py b/panel/migrations/0181_auto_20241109_2158.py new file mode 100644 index 0000000..a2e63c1 --- /dev/null +++ b/panel/migrations/0181_auto_20241109_2158.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2024-11-09 21:58 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0038_auto_20241109_2158'), + ('panel', '0180_auto_20241109_2044'), + ] + + operations = [ + migrations.AlterField( + 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.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 947314)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 882201)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 882201)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 882201)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 882201)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 888198)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 888198)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 888198)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 58, 37, 899226)), + ), + ] diff --git a/panel/migrations/0182_auto_20241109_2159.py b/panel/migrations/0182_auto_20241109_2159.py new file mode 100644 index 0000000..e90775d --- /dev/null +++ b/panel/migrations/0182_auto_20241109_2159.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-09 21:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0181_auto_20241109_2158'), + ] + + operations = [ + migrations.RemoveField( + model_name='chaincompany', + name='address', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 537562)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 422480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 422480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 422480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 422480)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 434010)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 434010)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 434010)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 21, 59, 10, 450694)), + ), + ] diff --git a/panel/migrations/0183_auto_20241109_2203.py b/panel/migrations/0183_auto_20241109_2203.py new file mode 100644 index 0000000..4374210 --- /dev/null +++ b/panel/migrations/0183_auto_20241109_2203.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-11-09 22:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0182_auto_20241109_2159'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 763253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 691384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 691384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 691384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 691384)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 698393)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 697392)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 697392)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 2, 59, 706590)), + ), + ] diff --git a/panel/migrations/0184_auto_20241109_2208.py b/panel/migrations/0184_auto_20241109_2208.py new file mode 100644 index 0000000..6fdd6e0 --- /dev/null +++ b/panel/migrations/0184_auto_20241109_2208.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-09 22:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0183_auto_20241109_2203'), + ] + + 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, 22, 8, 25, 422078)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 363172)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 363172)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 363172)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 363172)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 366168)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 366168)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 366168)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 22, 8, 25, 375760)), + ), + ] diff --git a/panel/migrations/0185_auto_20241110_1129.py b/panel/migrations/0185_auto_20241110_1129.py new file mode 100644 index 0000000..171751d --- /dev/null +++ b/panel/migrations/0185_auto_20241110_1129.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-10 11:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0184_auto_20241109_2208'), + ] + + 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, 11, 29, 26, 335397)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 79813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 79813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 79813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 79813)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 85030)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 85030)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 85030)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 11, 29, 26, 93723)), + ), + ] diff --git a/panel/migrations/0186_auto_20241110_1433.py b/panel/migrations/0186_auto_20241110_1433.py new file mode 100644 index 0000000..cfab134 --- /dev/null +++ b/panel/migrations/0186_auto_20241110_1433.py @@ -0,0 +1,68 @@ +# Generated by Django 3.2.13 on 2024-11-10 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0185_auto_20241110_1129'), + ] + + 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)), + ('start_time', models.TimeField(null=True)), + ('end_time', models.TimeField(null=True)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 959936)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 907067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 907067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 907067)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 907067)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 910167)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 910167)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 910167)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 14, 33, 20, 918515)), + ), + ] diff --git a/panel/migrations/0187_auto_20241110_2303.py b/panel/migrations/0187_auto_20241110_2303.py new file mode 100644 index 0000000..8540282 --- /dev/null +++ b/panel/migrations/0187_auto_20241110_2303.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-10 23:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0186_auto_20241110_1433'), + ] + + 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, 3, 1, 915702)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 673813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 672814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 673813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 673813)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 682808)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 682808)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 682808)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 3, 1, 702796)), + ), + ] diff --git a/panel/migrations/0188_auto_20241112_1550.py b/panel/migrations/0188_auto_20241112_1550.py new file mode 100644 index 0000000..8f982ae --- /dev/null +++ b/panel/migrations/0188_auto_20241112_1550.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-12 15:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0187_auto_20241110_2303'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='amount', + field=models.FloatField(default=0), + ), + 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, 15, 49, 40, 662990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 162328)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 162328)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 162328)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 162328)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 166317)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 166317)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 166317)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 49, 40, 174296)), + ), + ] diff --git a/panel/migrations/0189_auto_20241116_2114.py b/panel/migrations/0189_auto_20241116_2114.py new file mode 100644 index 0000000..0826624 --- /dev/null +++ b/panel/migrations/0189_auto_20241116_2114.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-11-16 21:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0188_auto_20241112_1550'), + ] + + 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.AddField( + model_name='guilds', + name='registerar_role', + field=models.CharField(max_length=50, null=True), + ), + 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_kill_house', + field=models.ManyToManyField(blank=True, null=True, related_name='steward_kill_houses', to='panel.KillHouse'), + ), + 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, related_name='_panel_guilds_stewards_+', to='panel.Guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 32, 19452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 968938)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 968938)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 968938)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 968938)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 972939)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 972939)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 972939)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 21, 14, 31, 980442)), + ), + ] diff --git a/panel/migrations/0190_auto_20241117_1117.py b/panel/migrations/0190_auto_20241117_1117.py new file mode 100644 index 0000000..59cb49a --- /dev/null +++ b/panel/migrations/0190_auto_20241117_1117.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-11-17 11: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', '0189_auto_20241116_2114'), + ] + + 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, 11, 17, 43, 89664)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 26943)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 26943)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 26943)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 26943)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 30036)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 30036)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 30036)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 17, 43, 38610)), + ), + 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, null=True, 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/0191_auto_20241117_1124.py b/panel/migrations/0191_auto_20241117_1124.py new file mode 100644 index 0000000..6aad733 --- /dev/null +++ b/panel/migrations/0191_auto_20241117_1124.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-17 11:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0190_auto_20241117_1117'), + ] + + 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, 11, 24, 48, 765797)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 713297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 713297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 713297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 713297)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 716288)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 716288)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 716288)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 11, 24, 48, 724266)), + ), + ] diff --git a/panel/migrations/0192_auto_20241119_1120.py b/panel/migrations/0192_auto_20241119_1120.py new file mode 100644 index 0000000..e4a882d --- /dev/null +++ b/panel/migrations/0192_auto_20241119_1120.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-19 11:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0191_auto_20241117_1124'), + ] + + 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, 19, 11, 19, 54, 172183)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 114805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 114805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 114805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 114805)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 124723)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 124723)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 124723)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 19, 11, 19, 54, 124723)), + ), + ] diff --git a/panel/migrations/0193_auto_20241120_0826.py b/panel/migrations/0193_auto_20241120_0826.py new file mode 100644 index 0000000..b3096bd --- /dev/null +++ b/panel/migrations/0193_auto_20241120_0826.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-20 08:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0192_auto_20241119_1120'), + ] + + 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, 26, 24, 110679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 49295)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 26, 24, 65031)), + ), + ] diff --git a/panel/migrations/0194_auto_20241126_1925.py b/panel/migrations/0194_auto_20241126_1925.py new file mode 100644 index 0000000..8424ce0 --- /dev/null +++ b/panel/migrations/0194_auto_20241126_1925.py @@ -0,0 +1,438 @@ +# Generated by Django 3.2.13 on 2024-11-26 19: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', '0193_auto_20241120_0826'), + ] + + operations = [ + migrations.RenameField( + model_name='rolesproducts', + old_name='accepted_allocated_quantity', + new_name='free_buying_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='accepted_allocated_weight', + new_name='free_buying_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='allocated_quantity', + new_name='loss_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='allocated_quantity_from', + new_name='out_province_allocated_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='allocated_weight', + new_name='out_province_allocated_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='allocated_weight_from', + new_name='pos_allocated_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='free_buying_bars_carcasses_quantity', + new_name='province_allocated_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='free_buying_bars_carcasses_weight', + new_name='province_allocated_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='free_buying_bars_quantity', + new_name='province_free_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='free_buying_bars_weight', + new_name='province_free_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='free_sale_quantity', + new_name='province_governmental_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='free_sale_weight', + new_name='province_governmental_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='live_bars_carcasses_quantity', + new_name='receive_free_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='live_bars_carcasses_weight', + new_name='receive_free_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='live_bars_quantity', + new_name='receive_governmental_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='live_bars_weight', + new_name='receive_governmental_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='number_of_accepted_allocations', + new_name='total_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='number_of_free_buying_bars', + new_name='total_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='number_of_live_bars', + new_name='total_free_bars_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='number_of_rejected_allocations', + new_name='total_free_bars_carcasses_weight', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='number_of_returned_allocations', + new_name='total_governmental_carcasses_quantity', + ), + migrations.RenameField( + model_name='rolesproducts', + old_name='rejected_allocated_quantity', + new_name='total_governmental_carcasses_weight', + ), + 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_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.RemoveField( + model_name='stewardallocation', + name='steward', + ), + 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='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.AddField( + model_name='killhousebarlimitation', + name='allow', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='weight_loss', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='automatic_accept', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='image', + field=models.CharField(max_length=500, null=True), + ), + 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.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.AddField( + model_name='rolesproducts', + name='free_price', + field=models.IntegerField(default=0), + ), + 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.AddField( + model_name='stewardallocation', + name='approved_price_status', + field=models.BooleanField(default=True), + ), + 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, 26, 19, 24, 59, 667462)), + ), + migrations.AlterField( + model_name='killhousepurchaserequest', + name='limitation_number', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='newproduct', + name='approved_price', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 615933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 615933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 615933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 615933)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 619437)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 619437)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 619437)), + ), + migrations.AlterField( + 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='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='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='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 24, 59, 626948)), + ), + 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, 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', 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, + }, + ), + 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, null=True, 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, + }, + ), + 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, 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)), + ('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, + }, + ), + 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, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allocation_limit', models.IntegerField(default=0)), + ('allocation_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='killhousestewardguildrelation_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_relation', to='panel.guilds')), + ('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.guilds')), + ], + options={ + 'abstract': False, + }, + ), + 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, 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)), + ('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, + }, + ), + 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, 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()), + ('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)), + ('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/0195_auto_20241126_1928.py b/panel/migrations/0195_auto_20241126_1928.py new file mode 100644 index 0000000..105e5b6 --- /dev/null +++ b/panel/migrations/0195_auto_20241126_1928.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-11-26 19:28 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0194_auto_20241126_1925'), + ] + + 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, 26, 19, 28, 23, 294939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 245940)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 244939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 245940)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 244939)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 248940)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 248940)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 248940)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 19, 28, 23, 256939)), + ), + ] diff --git a/panel/migrations/0196_auto_20241127_1001.py b/panel/migrations/0196_auto_20241127_1001.py new file mode 100644 index 0000000..e1c2bc8 --- /dev/null +++ b/panel/migrations/0196_auto_20241127_1001.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-11-27 10:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0195_auto_20241126_1928'), + ] + + 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, 10, 1, 14, 631702)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 582156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 582156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 582156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 582156)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 586162)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 586162)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 586162)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 10, 1, 14, 594173)), + ), + ] diff --git a/panel/migrations/0197_auto_20241201_1026.py b/panel/migrations/0197_auto_20241201_1026.py new file mode 100644 index 0000000..bb7d745 --- /dev/null +++ b/panel/migrations/0197_auto_20241201_1026.py @@ -0,0 +1,1155 @@ +# Generated by Django 3.2.13 on 2024-12-01 10:26 + +import datetime +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0196_auto_20241127_1001'), + ] + + operations = [ + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='coldhouseallocations', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='coldhouseallocations', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + 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.AddField( + model_name='killhouseassignmentinformation', + name='temporary_deleted', + 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_deleted', + 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_deleted', + 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_deleted', + 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_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + 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.AddField( + model_name='poultryrequest', + name='temporary_deleted', + 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_deleted', + 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_deleted', + 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_deleted', + 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_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + 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='adminx', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='agenotificationpoultry', + 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='bardocumentstatus', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='baseoutprovincecarcassesbuyer', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='broadcastprice', + 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='chainallocation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='chaincompany', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='chaincompanytransaction', + 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='chickenagerange', + 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='citylivestock', + 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='citypoultry', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='citysupervisor', + 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='dispenser', + 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, 12, 1, 10, 26, 12, 303109)), + ), + 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='guildsteward', + 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='improvinglivestock', + 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='internaltransaction', + 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='jahadinspector', + 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='killhousebarlimitation', + 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='killhousepricepermission', + 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='killhousestewardguildrelation', + 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='movingtext', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='movingtextdashboardstatus', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='movingtextrole', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='movingtextwithrole', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='newproduct', + 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, 12, 1, 10, 26, 12, 252069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 26, 12, 252069)), + ), + 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, 12, 1, 10, 26, 12, 252069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 26, 12, 252069)), + ), + migrations.AlterField( + model_name='outofprovincesellingcarcassespermission', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='outprovincecarcassesbuyer', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='outprovincepoultryrequestbuyer', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='outprovincesalelimitation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='paymentdeadline', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='paymentgatewaypercentage', + 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='percentageofwagetype', + 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='posmachinetransactions', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='postransactions', + 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, 12, 1, 10, 26, 12, 256065)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 1, 10, 26, 12, 256065)), + ), + 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, 12, 1, 10, 26, 12, 256065)), + ), + 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='poultryexport', + 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='poultryoutprovincerequest', + 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='productpricingtype', + 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='reports', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='reportsubmissiontime', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='reportsusers', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='rolesproducts', + 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='sharetype', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='slaughterhousetransaction', + 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='stewardfreesalebarinformation', + 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='superadmin', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='supporter', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='systemwallet', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='timerange', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='totalpaymentgatewaypercentage', + 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, 12, 1, 10, 26, 12, 264064)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='totalwageinformation', + 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='userreports', + 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='vetfarmaggregatepermission', + 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='wagetype', + 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.AlterField( + model_name='zarinpalaccounts', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + ] diff --git a/panel/migrations/0198_auto_20241203_1130.py b/panel/migrations/0198_auto_20241203_1130.py new file mode 100644 index 0000000..9597b7d --- /dev/null +++ b/panel/migrations/0198_auto_20241203_1130.py @@ -0,0 +1,68 @@ +# Generated by Django 3.2.13 on 2024-12-03 11:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0197_auto_20241201_1026'), + ] + + operations = [ + migrations.RemoveField( + model_name='agenotificationpoultry', + name='hour_send', + ), + 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, 11, 30, 26, 170286)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 111070)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 111070)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 111070)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 111070)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 114175)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 114175)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 114175)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 11, 30, 26, 121892)), + ), + ] diff --git a/panel/migrations/0199_auto_20241203_1240.py b/panel/migrations/0199_auto_20241203_1240.py new file mode 100644 index 0000000..fbae6f0 --- /dev/null +++ b/panel/migrations/0199_auto_20241203_1240.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-03 12:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0198_auto_20241203_1130'), + ] + + 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, 12, 40, 3, 237226)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 184184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 184184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 184184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 184184)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 188188)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 188188)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 188188)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 12, 40, 3, 195938)), + ), + ] diff --git a/panel/migrations/0200_auto_20241204_1557.py b/panel/migrations/0200_auto_20241204_1557.py new file mode 100644 index 0000000..b2d6e1b --- /dev/null +++ b/panel/migrations/0200_auto_20241204_1557.py @@ -0,0 +1,103 @@ +# Generated by Django 3.2.13 on 2024-12-04 15:57 + +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', '0199_auto_20241203_1240'), + ] + + 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, 15, 57, 7, 72878)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 18013)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 18013)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 18013)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 18013)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 21025)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 21025)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 21025)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 15, 57, 7, 29682)), + ), + 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/0201_auto_20241208_1125.py b/panel/migrations/0201_auto_20241208_1125.py new file mode 100644 index 0000000..4998b89 --- /dev/null +++ b/panel/migrations/0201_auto_20241208_1125.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-12-08 11:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0200_auto_20241204_1557'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 8, 34829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 672925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 672925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 672925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 672925)), + ), + 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='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, 24, 6, 676938)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 676938)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 676938)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 24, 6, 684698)), + ), + ] diff --git a/panel/migrations/0202_auto_20241208_1514.py b/panel/migrations/0202_auto_20241208_1514.py new file mode 100644 index 0000000..082c226 --- /dev/null +++ b/panel/migrations/0202_auto_20241208_1514.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-12-08 15:14 + +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', '0040_auto_20241208_1514'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0201_auto_20241208_1125'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 733678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 682802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 682802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 682802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 682802)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 686313)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 686313)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 686313)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 15, 14, 18, 694325)), + ), + 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/0203_auto_20241209_1548.py b/panel/migrations/0203_auto_20241209_1548.py new file mode 100644 index 0000000..6adcdf7 --- /dev/null +++ b/panel/migrations/0203_auto_20241209_1548.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-12-09 15:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0202_auto_20241208_1514'), + ] + + 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, 15, 48, 51, 256256)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 183297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 183297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 183297)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 183297)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 193460)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 193460)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 193460)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 15, 48, 51, 193460)), + ), + ] diff --git a/panel/migrations/0204_auto_20241211_1500.py b/panel/migrations/0204_auto_20241211_1500.py new file mode 100644 index 0000000..c8c9e3e --- /dev/null +++ b/panel/migrations/0204_auto_20241211_1500.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-12-11 15:00 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0203_auto_20241209_1548'), + ] + + 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='rolesproducts', + name='cold_house_allocated_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, 15, 0, 45, 754159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 15, 0, 45, 707094)), + ), + ] diff --git a/panel/migrations/0205_auto_20241214_1645.py b/panel/migrations/0205_auto_20241214_1645.py new file mode 100644 index 0000000..7ef2ca7 --- /dev/null +++ b/panel/migrations/0205_auto_20241214_1645.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-12-14 16:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0204_auto_20241211_1500'), + ] + + 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, 16, 45, 27, 124339)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 61103)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 61103)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 61103)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 61103)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 65122)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 65122)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 65122)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 16, 45, 27, 72892)), + ), + ] diff --git a/panel/migrations/0206_auto_20241216_1353.py b/panel/migrations/0206_auto_20241216_1353.py new file mode 100644 index 0000000..7046c0c --- /dev/null +++ b/panel/migrations/0206_auto_20241216_1353.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-12-16 13:53 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0205_auto_20241214_1645'), + ] + + 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, 13, 53, 0, 410974)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 13, 53, 0, 364988)), + ), + ] diff --git a/panel/migrations/0207_auto_20241218_1015.py b/panel/migrations/0207_auto_20241218_1015.py new file mode 100644 index 0000000..2d77ffa --- /dev/null +++ b/panel/migrations/0207_auto_20241218_1015.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-12-18 10:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0206_auto_20241216_1353'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='coldhouse', + name='address', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='coldhouse', + name='broadcast', + field=models.BooleanField(default=True), + ), + 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.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, 18, 10, 15, 32, 819489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 780374)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 10, 15, 32, 787926)), + ), + ] diff --git a/panel/migrations/0208_auto_20241218_1441.py b/panel/migrations/0208_auto_20241218_1441.py new file mode 100644 index 0000000..d11aac3 --- /dev/null +++ b/panel/migrations/0208_auto_20241218_1441.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-18 14:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0207_auto_20241218_1015'), + ] + + 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, 41, 16, 757344)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 694293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 694293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 694293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 694293)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 710228)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 710228)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 710228)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 41, 16, 714246)), + ), + ] diff --git a/panel/migrations/0209_auto_20241222_1149.py b/panel/migrations/0209_auto_20241222_1149.py new file mode 100644 index 0000000..de67530 --- /dev/null +++ b/panel/migrations/0209_auto_20241222_1149.py @@ -0,0 +1,121 @@ +# Generated by Django 3.2.13 on 2024-12-22 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', '0208_auto_20241218_1441'), + ] + + operations = [ + migrations.AddField( + model_name='poscompany', + name='active', + field=models.BooleanField(default=True), + ), + 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, 22, 11, 49, 34, 477747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 430379)), + ), + 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={ + 'abstract': False, + }, + ), + 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, 22, 11, 49, 34, 540705))), + ('session_last_seen_date', models.DateTimeField(default=datetime.datetime(2024, 12, 22, 11, 49, 34, 540705))), + ('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(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pos_device_session', to='panel.posmachine')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0210_auto_20241225_1127.py b/panel/migrations/0210_auto_20241225_1127.py new file mode 100644 index 0000000..83d0c67 --- /dev/null +++ b/panel/migrations/0210_auto_20241225_1127.py @@ -0,0 +1,113 @@ +# Generated by Django 3.2.13 on 2024-12-25 11: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', '0209_auto_20241222_1149'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 114317)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 177729)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 177729)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 67107)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 11, 27, 2, 82821)), + ), + 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, + }, + ), + 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/0211_auto_20241225_1631.py b/panel/migrations/0211_auto_20241225_1631.py new file mode 100644 index 0000000..370032f --- /dev/null +++ b/panel/migrations/0211_auto_20241225_1631.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-12-25 16:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0210_auto_20241225_1127'), + ] + + 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, 16, 31, 31, 914893)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 851368)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 851368)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 851368)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 851368)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 978320)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 978320)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 869267)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 869267)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 869267)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 16, 31, 31, 877299)), + ), + migrations.AlterUniqueTogether( + name='posdeviceversion', + unique_together={('company', 'code')}, + ), + ] diff --git a/panel/migrations/0212_auto_20241231_1547.py b/panel/migrations/0212_auto_20241231_1547.py new file mode 100644 index 0000000..a17b004 --- /dev/null +++ b/panel/migrations/0212_auto_20241231_1547.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-12-31 15:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0211_auto_20241225_1631'), + ] + + 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, 47, 17, 599995)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 665808)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 665808)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 552241)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 47, 17, 568176)), + ), + ] diff --git a/panel/migrations/0213_auto_20241231_2151.py b/panel/migrations/0213_auto_20241231_2151.py new file mode 100644 index 0000000..52823d0 --- /dev/null +++ b/panel/migrations/0213_auto_20241231_2151.py @@ -0,0 +1,92 @@ +# Generated by Django 3.2.13 on 2024-12-31 21: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', '0212_auto_20241231_1547'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 940342)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 874343)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 874343)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 874343)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 874343)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 39, 21346)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 39, 21346)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 878343)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 878343)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 878343)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 51, 38, 889343)), + ), + 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/0214_auto_20250107_0934.py b/panel/migrations/0214_auto_20250107_0934.py new file mode 100644 index 0000000..58efcac --- /dev/null +++ b/panel/migrations/0214_auto_20250107_0934.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-01-07 09:34 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0213_auto_20241231_2151'), + ] + + 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, 7, 9, 33, 49, 22369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 401610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 401610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 401610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 401610)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 49, 781408)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 49, 781408)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 422612)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 422612)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 422612)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 9, 33, 44, 471612)), + ), + ] diff --git a/panel/migrations/0215_auto_20250107_1815.py b/panel/migrations/0215_auto_20250107_1815.py new file mode 100644 index 0000000..f2efc20 --- /dev/null +++ b/panel/migrations/0215_auto_20250107_1815.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2025-01-07 18:15 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0214_auto_20250107_0934'), + ] + + operations = [ + migrations.AddField( + model_name='posmachinetransactions', + name='current_price', + field=models.IntegerField(default=0), + ), + 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, 18, 14, 40, 53497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 941614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 941614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 941614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 941614)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 40, 151562)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 40, 151562)), + ), + 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, 14, 39, 949383)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 949383)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 949383)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 14, 39, 964561)), + ), + ] diff --git a/panel/migrations/0216_auto_20250112_1928.py b/panel/migrations/0216_auto_20250112_1928.py new file mode 100644 index 0000000..3ff1a61 --- /dev/null +++ b/panel/migrations/0216_auto_20250112_1928.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2025-01-12 19: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 = [ + ('authentication', '0045_auto_20250112_1928'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0215_auto_20250107_1815'), + ] + + 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, 19, 28, 27, 345881)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 294882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 294882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 294882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 294882)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 408881)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 408881)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 297881)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 297881)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 297881)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 19, 28, 27, 305881)), + ), + 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/0217_auto_20250113_1620.py b/panel/migrations/0217_auto_20250113_1620.py new file mode 100644 index 0000000..99952f5 --- /dev/null +++ b/panel/migrations/0217_auto_20250113_1620.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-01-13 16:20 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0216_auto_20250112_1928'), + ] + + 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, 16, 20, 47, 111990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 58574)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 58574)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 58574)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 58574)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 166918)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 166918)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 62590)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 62590)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 62590)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 16, 20, 47, 70622)), + ), + ] diff --git a/panel/migrations/0218_auto_20250120_1050.py b/panel/migrations/0218_auto_20250120_1050.py new file mode 100644 index 0000000..5c08d7a --- /dev/null +++ b/panel/migrations/0218_auto_20250120_1050.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-01-20 10:50 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0217_auto_20250113_1620'), + ] + + 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, 20, 10, 50, 12, 753230)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 759716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 759716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 759716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 759716)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 14, 655701)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 14, 655701)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 763463)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 763463)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 763463)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 10, 50, 11, 992180)), + ), + ] diff --git a/panel/migrations/0219_auto_20250201_1511.py b/panel/migrations/0219_auto_20250201_1511.py new file mode 100644 index 0000000..d281074 --- /dev/null +++ b/panel/migrations/0219_auto_20250201_1511.py @@ -0,0 +1,138 @@ +# Generated by Django 3.2.13 on 2025-02-01 15: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', '0218_auto_20250120_1050'), + ] + + 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.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, 15, 11, 15, 450234)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 398187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 398187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 398187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 398187)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 513463)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 513463)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 401189)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 401189)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 401189)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 15, 11, 15, 410189)), + ), + 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, + }, + ), + 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/0220_auto_20250205_1307.py b/panel/migrations/0220_auto_20250205_1307.py new file mode 100644 index 0000000..1e97269 --- /dev/null +++ b/panel/migrations/0220_auto_20250205_1307.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-02-05 13:07 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0219_auto_20250201_1511'), + ] + + 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, 7, 28, 862584)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 716035)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 716035)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 716035)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 716035)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 29, 7645)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 29, 7645)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 723035)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 723035)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 723035)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 7, 28, 782036)), + ), + ] diff --git a/panel/migrations/0221_auto_20250209_0939.py b/panel/migrations/0221_auto_20250209_0939.py new file mode 100644 index 0000000..a92eecf --- /dev/null +++ b/panel/migrations/0221_auto_20250209_0939.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-09 09:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0220_auto_20250205_1307'), + ] + + 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, 39, 30, 225749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 172751)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 172751)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 172751)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 172751)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 289788)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 289788)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 175749)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 175749)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 175749)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 39, 30, 184749)), + ), + ] diff --git a/panel/migrations/0222_auto_20250209_1613.py b/panel/migrations/0222_auto_20250209_1613.py new file mode 100644 index 0000000..d947dde --- /dev/null +++ b/panel/migrations/0222_auto_20250209_1613.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2025-02-09 16: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', '0221_auto_20250209_0939'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 549895)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 613475)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 613475)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 486403)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 16, 13, 19, 502384)), + ), + 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/0223_auto_20250210_1600.py b/panel/migrations/0223_auto_20250210_1600.py new file mode 100644 index 0000000..84a89f0 --- /dev/null +++ b/panel/migrations/0223_auto_20250210_1600.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2025-02-10 16:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0222_auto_20250209_1613'), + ] + + 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, 16, 0, 26, 619702)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 468716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 468716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 468716)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 468716)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 821806)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 821806)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 476826)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 476826)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 476826)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 16, 0, 26, 504412)), + ), + ] diff --git a/panel/migrations/0224_auto_20250211_1239.py b/panel/migrations/0224_auto_20250211_1239.py new file mode 100644 index 0000000..0767165 --- /dev/null +++ b/panel/migrations/0224_auto_20250211_1239.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-11 12:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0223_auto_20250210_1600'), + ] + + 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, 12, 39, 42, 411052)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 343706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 343706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 343706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 343706)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 470189)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 470189)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 359653)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 359653)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 359653)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 12, 39, 42, 359653)), + ), + ] diff --git a/panel/migrations/0225_auto_20250212_0919.py b/panel/migrations/0225_auto_20250212_0919.py new file mode 100644 index 0000000..b03562e --- /dev/null +++ b/panel/migrations/0225_auto_20250212_0919.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-02-12 09:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0224_auto_20250211_1239'), + ] + + 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, 9, 19, 15, 157734)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 103424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 103424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 103424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 103424)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 222792)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 222792)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 105427)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 105427)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 105427)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 19, 15, 114446)), + ), + ] diff --git a/panel/migrations/0226_auto_20250212_0946.py b/panel/migrations/0226_auto_20250212_0946.py new file mode 100644 index 0000000..c8307ca --- /dev/null +++ b/panel/migrations/0226_auto_20250212_0946.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2025-02-12 09:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0225_auto_20250212_0919'), + ] + + 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, 45, 59, 492789)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 555831)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 555831)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 45, 59, 437573)), + ), + ] diff --git a/panel/migrations/0227_auto_20250212_0949.py b/panel/migrations/0227_auto_20250212_0949.py new file mode 100644 index 0000000..de64c4c --- /dev/null +++ b/panel/migrations/0227_auto_20250212_0949.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-02-12 09:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0226_auto_20250212_0946'), + ] + + 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, 9, 49, 26, 610351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 673460)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 673460)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 563177)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 49, 26, 578946)), + ), + ] diff --git a/panel/migrations/0228_auto_20250212_1728.py b/panel/migrations/0228_auto_20250212_1728.py new file mode 100644 index 0000000..8177c79 --- /dev/null +++ b/panel/migrations/0228_auto_20250212_1728.py @@ -0,0 +1,98 @@ +# Generated by Django 3.2.13 on 2025-02-12 17: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', '0227_auto_20250212_0949'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 442818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 388953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 388953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 388953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 388953)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 502622)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 502622)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 390956)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 390956)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 390956)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 28, 35, 390956)), + ), + 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/0229_auto_20250212_1730.py b/panel/migrations/0229_auto_20250212_1730.py new file mode 100644 index 0000000..0c8ae1f --- /dev/null +++ b/panel/migrations/0229_auto_20250212_1730.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-02-12 17:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0228_auto_20250212_1728'), + ] + + 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, 17, 30, 1, 532352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 461208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 461208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 461208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 461208)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 616988)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 616988)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 465219)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 465219)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 465219)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 17, 30, 1, 474992)), + ), + ] diff --git a/panel/migrations/0230_auto_20250216_1323.py b/panel/migrations/0230_auto_20250216_1323.py new file mode 100644 index 0000000..32f204f --- /dev/null +++ b/panel/migrations/0230_auto_20250216_1323.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-02-16 13:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0229_auto_20250212_1730'), + ] + + 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, 13, 23, 46, 689731)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 630487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 630487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 630487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 630487)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 772826)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 774567)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 634242)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 634242)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 634242)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 13, 23, 46, 644295)), + ), + ] diff --git a/panel/migrations/0231_auto_20250222_1151.py b/panel/migrations/0231_auto_20250222_1151.py new file mode 100644 index 0000000..cb4ad54 --- /dev/null +++ b/panel/migrations/0231_auto_20250222_1151.py @@ -0,0 +1,154 @@ +# Generated by Django 3.2.13 on 2025-02-22 11:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0230_auto_20250216_1323'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='inquiry_date', + field=models.DateField(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.AddField( + model_name='posmachinetransactions', + name='pos_date', + field=models.BigIntegerField(default=0), + ), + 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='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', + field=models.BigIntegerField(default=0), + ), + 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, 22, 11, 50, 59, 723580)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 660322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 660322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 660322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 660322)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 790674)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 790674)), + ), + 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, 22, 11, 50, 59, 672047)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 672047)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 672047)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 50, 59, 682089)), + ), + ] diff --git a/panel/migrations/0232_auto_20250223_1025.py b/panel/migrations/0232_auto_20250223_1025.py new file mode 100644 index 0000000..2e1aa4e --- /dev/null +++ b/panel/migrations/0232_auto_20250223_1025.py @@ -0,0 +1,92 @@ +# Generated by Django 3.2.13 on 2025-02-23 10:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0231_auto_20250222_1151'), + ] + + 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(max_length=250, null=True)), + ('aspxauth', models.TextField(null=True)), + ], + ), + migrations.AddField( + model_name='bardifferencerequest', + name='acceptor_date', + field=models.DateTimeField(null=True), + ), + 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, 10, 25, 25, 819845)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 748184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 747677)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 748184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 747677)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 903322)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 903322)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 752249)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 752249)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 752249)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 25, 25, 762833)), + ), + ] diff --git a/panel/migrations/0233_auto_20250223_1547.py b/panel/migrations/0233_auto_20250223_1547.py new file mode 100644 index 0000000..d245b13 --- /dev/null +++ b/panel/migrations/0233_auto_20250223_1547.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-02-23 15:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0232_auto_20250223_1025'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='share_debt_counting_wage', + field=models.BooleanField(default=False), + ), + 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, 23, 15, 47, 33, 785895)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 849450)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 849450)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 738349)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 15, 47, 33, 754215)), + ), + ] diff --git a/panel/migrations/0234_auto_20250224_1402.py b/panel/migrations/0234_auto_20250224_1402.py new file mode 100644 index 0000000..64f020c --- /dev/null +++ b/panel/migrations/0234_auto_20250224_1402.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-02-24 14:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0233_auto_20250223_1547'), + ] + + operations = [ + migrations.DeleteModel( + name='CookieSamasat', + ), + migrations.RemoveField( + model_name='killhouse', + name='share_debt_counting_wage', + ), + migrations.RemoveField( + model_name='killhouse', + name='unique_identifier', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 749231)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 694354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 694354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 694354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 694354)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 815248)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 815248)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 697391)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 697391)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 697391)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 2, 13, 707359)), + ), + ] diff --git a/panel/migrations/0235_auto_20250224_1407.py b/panel/migrations/0235_auto_20250224_1407.py new file mode 100644 index 0000000..a36aca1 --- /dev/null +++ b/panel/migrations/0235_auto_20250224_1407.py @@ -0,0 +1,76 @@ +# Generated by Django 3.2.13 on 2025-02-24 14:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0234_auto_20250224_1402'), + ] + + 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, 14, 7, 17, 316001)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 188004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 188004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 188004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 188004)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 454003)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 454003)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 197002)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 197002)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 197002)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 14, 7, 17, 219002)), + ), + ] diff --git a/panel/migrations/0236_auto_20250224_1528.py b/panel/migrations/0236_auto_20250224_1528.py new file mode 100644 index 0000000..605cba7 --- /dev/null +++ b/panel/migrations/0236_auto_20250224_1528.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-02-24 15:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0235_auto_20250224_1407'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='share_debt_counting_wage', + field=models.BooleanField(default=False), + ), + 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, 24, 15, 27, 54, 484715)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 420671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 420671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 420671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 420671)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 560233)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 560233)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 424671)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 424671)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 424671)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 15, 27, 54, 436678)), + ), + ] diff --git a/panel/migrations/0237_auto_20250225_1158.py b/panel/migrations/0237_auto_20250225_1158.py new file mode 100644 index 0000000..c3385f7 --- /dev/null +++ b/panel/migrations/0237_auto_20250225_1158.py @@ -0,0 +1,103 @@ +# Generated by Django 3.2.13 on 2025-02-25 11:58 + +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_20250224_1528'), + ] + + 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, 58, 44, 991675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 936678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 936678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 936678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 936678)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 45, 54308)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 45, 54308)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 939678)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 939678)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 939678)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 58, 44, 950638)), + ), + 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/0238_auto_20250226_0946.py b/panel/migrations/0238_auto_20250226_0946.py new file mode 100644 index 0000000..3fc7141 --- /dev/null +++ b/panel/migrations/0238_auto_20250226_0946.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-26 09:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0237_auto_20250225_1158'), + ] + + 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, 46, 31, 542009)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 77775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 77775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 77775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 77775)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 32, 20380)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 32, 20380)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 144776)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 144776)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 144776)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 46, 31, 184306)), + ), + ] diff --git a/panel/migrations/0239_auto_20250303_2034.py b/panel/migrations/0239_auto_20250303_2034.py new file mode 100644 index 0000000..097eaf0 --- /dev/null +++ b/panel/migrations/0239_auto_20250303_2034.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-03 20:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0238_auto_20250226_0946'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 427097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 375096)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 375096)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 375096)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 375096)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 493252)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 493252)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 378096)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 378096)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 378096)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 34, 11, 387096)), + ), + ] diff --git a/panel/migrations/0240_auto_20250303_2036.py b/panel/migrations/0240_auto_20250303_2036.py new file mode 100644 index 0000000..b073701 --- /dev/null +++ b/panel/migrations/0240_auto_20250303_2036.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-03 20:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0239_auto_20250303_2034'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 715921)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 657882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 657882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 657882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 657882)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 779921)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 780920)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 661919)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 661919)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 661919)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 20, 35, 52, 671928)), + ), + ] diff --git a/panel/migrations/0241_auto_20250304_1734.py b/panel/migrations/0241_auto_20250304_1734.py new file mode 100644 index 0000000..4f601b5 --- /dev/null +++ b/panel/migrations/0241_auto_20250304_1734.py @@ -0,0 +1,106 @@ +# Generated by Django 3.2.13 on 2025-03-04 17:34 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0002_livestock'), + ('panel', '0240_auto_20250303_2036'), + ] + + operations = [ + migrations.AddField( + model_name='otherproducts', + name='targetunit', + field=models.CharField(default='g', max_length=100), + ), + 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='posmachinetransactions', + name='live_stock', + field=models.BooleanField(default=False), + ), + 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.AddField( + model_name='poultry', + name='interest_license_id', + field=models.CharField(max_length=100, null=True), + ), + 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, 4, 17, 34, 39, 1489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 939161)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 939161)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 939161)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 939161)), + ), + 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, 4, 17, 34, 39, 78899)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 39, 78899)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 943157)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 943157)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 943157)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 34, 38, 955162)), + ), + ] diff --git a/panel/migrations/0242_auto_20250307_1727.py b/panel/migrations/0242_auto_20250307_1727.py new file mode 100644 index 0000000..e3a4f45 --- /dev/null +++ b/panel/migrations/0242_auto_20250307_1727.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-03-07 17:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0241_auto_20250304_1734'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 823058)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 757814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 757814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 757814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 757814)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 884529)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 884529)), + ), + 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, 17, 27, 0, 773527)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 773527)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 773527)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 17, 27, 0, 773527)), + ), + ] diff --git a/panel/migrations/0243_auto_20250317_0032.py b/panel/migrations/0243_auto_20250317_0032.py new file mode 100644 index 0000000..c96d496 --- /dev/null +++ b/panel/migrations/0243_auto_20250317_0032.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-03-17 00: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', '0242_auto_20250307_1727'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 308195)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 47193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 47193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 47193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 47193)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 551193)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 551193)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 64192)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 64192)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 64192)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 17, 0, 30, 43, 100193)), + ), + 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/0244_auto_20250414_1439.py b/panel/migrations/0244_auto_20250414_1439.py new file mode 100644 index 0000000..4bfdad1 --- /dev/null +++ b/panel/migrations/0244_auto_20250414_1439.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-04-14 14: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_20250317_0032'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 298277)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 241375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 241375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 241375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 241375)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 366820)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 366820)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 244367)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 244367)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 244367)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 14, 38, 52, 255990)), + ), + 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/0245_auto_20250420_1113.py b/panel/migrations/0245_auto_20250420_1113.py new file mode 100644 index 0000000..f6b4657 --- /dev/null +++ b/panel/migrations/0245_auto_20250420_1113.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-04-20 11:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0244_auto_20250414_1439'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='register_type', + field=models.CharField(default='manual', max_length=250), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 286723)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 232724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 232724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 232724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 232724)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 352762)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 352762)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 235724)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 235724)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 235724)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 13, 49, 246724)), + ), + ] diff --git a/panel/migrations/0246_auto_20250430_1317.py b/panel/migrations/0246_auto_20250430_1317.py new file mode 100644 index 0000000..c802fb3 --- /dev/null +++ b/panel/migrations/0246_auto_20250430_1317.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-04-30 13:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0245_auto_20250420_1113'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='final_accept', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='price_confirmation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='input_price_confirmation_code', + field=models.CharField(max_length=10, null=True), + ), + 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, 30, 13, 17, 17, 389665)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 254675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 253668)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 253668)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 253668)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 553665)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 553665)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 262669)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 262669)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 262669)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 30, 13, 17, 17, 280666)), + ), + ] diff --git a/panel/migrations/0247_auto_20250503_1405.py b/panel/migrations/0247_auto_20250503_1405.py new file mode 100644 index 0000000..7090385 --- /dev/null +++ b/panel/migrations/0247_auto_20250503_1405.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2025-05-03 14: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', '0246_auto_20250430_1317'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 990277)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 41, 63554)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 41, 63554)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 14, 5, 40, 942941)), + ), + 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/0248_auto_20250504_1447.py b/panel/migrations/0248_auto_20250504_1447.py new file mode 100644 index 0000000..9f585d5 --- /dev/null +++ b/panel/migrations/0248_auto_20250504_1447.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-05-04 14: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', '0247_auto_20250503_1405'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 996854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 893764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 893764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 893764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 893764)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 53, 142008)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 53, 142008)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 915513)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 915513)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 915513)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 14, 46, 52, 927139)), + ), + 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)), + ('shaba', 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/0249_auto_20250505_1511.py b/panel/migrations/0249_auto_20250505_1511.py new file mode 100644 index 0000000..a54d87e --- /dev/null +++ b/panel/migrations/0249_auto_20250505_1511.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-05-05 15:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0248_auto_20250504_1447'), + ] + + 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, 15, 11, 7, 590877)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 537456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 537456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 537456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 537456)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 659846)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 659846)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 541473)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 541473)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 541473)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 15, 11, 7, 551248)), + ), + ] diff --git a/panel/migrations/0250_auto_20250506_1102.py b/panel/migrations/0250_auto_20250506_1102.py new file mode 100644 index 0000000..6850841 --- /dev/null +++ b/panel/migrations/0250_auto_20250506_1102.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-06 11:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0249_auto_20250505_1511'), + ] + + 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, 11, 2, 25, 340657)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 245032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 245032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 245032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 245032)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 25, 985390)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 25, 985390)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 499443)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 461382)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 462384)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 11, 2, 24, 848062)), + ), + ] diff --git a/panel/migrations/0251_auto_20250510_1213.py b/panel/migrations/0251_auto_20250510_1213.py new file mode 100644 index 0000000..79e7dd5 --- /dev/null +++ b/panel/migrations/0251_auto_20250510_1213.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-10 12:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0250_auto_20250506_1102'), + ] + + 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, 13, 42, 820270)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 51326)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 50329)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 51326)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 50329)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 43, 281038)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 43, 281038)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 520073)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 520073)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 520073)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 13, 42, 530046)), + ), + ] diff --git a/panel/migrations/0252_auto_20250511_1501.py b/panel/migrations/0252_auto_20250511_1501.py new file mode 100644 index 0000000..4b904bc --- /dev/null +++ b/panel/migrations/0252_auto_20250511_1501.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-11 15:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0251_auto_20250510_1213'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 640188)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 587224)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 587224)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 587224)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 587224)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 706663)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 706663)), + ), + 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, 15, 0, 52, 590317)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 590317)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 590317)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 15, 0, 52, 599680)), + ), + ] diff --git a/panel/migrations/0253_auto_20250517_0916.py b/panel/migrations/0253_auto_20250517_0916.py new file mode 100644 index 0000000..4f4d367 --- /dev/null +++ b/panel/migrations/0253_auto_20250517_0916.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-17 09:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0252_auto_20250511_1501'), + ] + + 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, 15, 23, 774665)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 720659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 720659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 720659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 720659)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 841698)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 841698)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 724660)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 724660)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 724660)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 15, 23, 734667)), + ), + ] diff --git a/panel/migrations/0254_auto_20250518_0912.py b/panel/migrations/0254_auto_20250518_0912.py new file mode 100644 index 0000000..cea3e31 --- /dev/null +++ b/panel/migrations/0254_auto_20250518_0912.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-05-18 09:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0253_auto_20250517_0916'), + ] + + 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.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, 18, 9, 12, 43, 368714)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 431547)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 431547)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 305031)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 9, 12, 43, 327010)), + ), + ] diff --git a/panel/migrations/0255_auto_20250518_1229.py b/panel/migrations/0255_auto_20250518_1229.py new file mode 100644 index 0000000..07c551e --- /dev/null +++ b/panel/migrations/0255_auto_20250518_1229.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-18 12:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0254_auto_20250518_0912'), + ] + + 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, 12, 29, 8, 88178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 33245)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 33245)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 33245)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 33245)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 156828)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 156828)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 37000)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 35989)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 35989)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 12, 29, 8, 46448)), + ), + ] diff --git a/panel/migrations/0256_auto_20250520_1146.py b/panel/migrations/0256_auto_20250520_1146.py new file mode 100644 index 0000000..12c2f18 --- /dev/null +++ b/panel/migrations/0256_auto_20250520_1146.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-20 11:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0255_auto_20250518_1229'), + ] + + 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, 45, 45, 901244)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 847725)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 847725)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 847725)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 847725)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 965760)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 965760)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 850723)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 850723)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 850723)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 45, 45, 860724)), + ), + ] diff --git a/panel/migrations/0257_auto_20250526_1029.py b/panel/migrations/0257_auto_20250526_1029.py new file mode 100644 index 0000000..f2e4f97 --- /dev/null +++ b/panel/migrations/0257_auto_20250526_1029.py @@ -0,0 +1,103 @@ +# Generated by Django 3.2.13 on 2025-05-26 10: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 = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0256_auto_20250520_1146'), + ] + + 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, 10, 29, 45, 345882)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 395962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 395962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 395962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 395962)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 45, 538289)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 45, 538289)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 401991)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 401991)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 401991)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 10, 29, 44, 937483)), + ), + 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/0258_auto_20250527_1054.py b/panel/migrations/0258_auto_20250527_1054.py new file mode 100644 index 0000000..335c66b --- /dev/null +++ b/panel/migrations/0258_auto_20250527_1054.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-05-27 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0257_auto_20250526_1029'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 399241)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 343307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 343307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 343307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 343307)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 467296)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 467296)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 346399)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 346399)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 346399)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 54, 19, 356509)), + ), + ] diff --git a/panel/migrations/0259_auto_20250527_1249.py b/panel/migrations/0259_auto_20250527_1249.py new file mode 100644 index 0000000..0924248 --- /dev/null +++ b/panel/migrations/0259_auto_20250527_1249.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2025-05-27 12:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0258_auto_20250527_1054'), + ] + + 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='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.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.AddField( + model_name='guilds', + name='temporary_registration', + field=models.BooleanField(default=False), + ), + 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, 12, 48, 56, 486837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 435273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 435273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 435273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 435273)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 549956)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 549956)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 437281)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 437281)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 437281)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 48, 56, 447318)), + ), + ] diff --git a/panel/migrations/0260_auto_20250528_1439.py b/panel/migrations/0260_auto_20250528_1439.py new file mode 100644 index 0000000..8fcf70c --- /dev/null +++ b/panel/migrations/0260_auto_20250528_1439.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-05-28 14: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', '0259_auto_20250527_1249'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 41, 10561)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 917963)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 917963)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 917963)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 917963)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 42, 393618)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 42, 393618)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 921978)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 921978)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 921978)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 14, 37, 38, 990944)), + ), + 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=1500)), + ('wholesaler_price', models.IntegerField(default=2000)), + ('retailer_price', models.IntegerField(default=4000)), + ('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/0261_auto_20250531_1003.py b/panel/migrations/0261_auto_20250531_1003.py new file mode 100644 index 0000000..218052d --- /dev/null +++ b/panel/migrations/0261_auto_20250531_1003.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-05-31 10:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0260_auto_20250528_1439'), + ] + + 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='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, 3, 6, 292480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 235571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 235571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 235571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 235571)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 362343)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 362343)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 239494)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 239494)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 239494)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 3, 6, 248494)), + ), + ] diff --git a/panel/migrations/0262_auto_20250531_1016.py b/panel/migrations/0262_auto_20250531_1016.py new file mode 100644 index 0000000..ca7f948 --- /dev/null +++ b/panel/migrations/0262_auto_20250531_1016.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 10:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0261_auto_20250531_1003'), + ] + + operations = [ + migrations.AlterField( + model_name='chickencommissionprices', + name='date', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 641485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 584734)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 584734)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 584734)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 584734)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 767095)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 767095)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 588532)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 588532)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 588532)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 16, 9, 598749)), + ), + ] diff --git a/panel/migrations/0263_auto_20250531_1131.py b/panel/migrations/0263_auto_20250531_1131.py new file mode 100644 index 0000000..589ddfd --- /dev/null +++ b/panel/migrations/0263_auto_20250531_1131.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 11:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0262_auto_20250531_1016'), + ] + + 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, 11, 30, 50, 973520)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 532077)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 532077)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 532077)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 532077)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 51, 864903)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 51, 864903)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 547882)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 547882)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 547882)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 11, 30, 48, 559940)), + ), + ] diff --git a/panel/migrations/0264_auto_20250531_1211.py b/panel/migrations/0264_auto_20250531_1211.py new file mode 100644 index 0000000..d40ca5f --- /dev/null +++ b/panel/migrations/0264_auto_20250531_1211.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-31 12:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0263_auto_20250531_1131'), + ] + + 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, 11, 33, 575850)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 384220)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 384220)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 384220)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 384220)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 678704)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 678704)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 388984)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 388984)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 388984)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 11, 33, 401334)), + ), + ] diff --git a/panel/migrations/0265_auto_20250531_1633.py b/panel/migrations/0265_auto_20250531_1633.py new file mode 100644 index 0000000..90668a8 --- /dev/null +++ b/panel/migrations/0265_auto_20250531_1633.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 16:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0264_auto_20250531_1211'), + ] + + 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, 16, 32, 59, 798954)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 868045)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 868045)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 739544)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 16, 32, 59, 755340)), + ), + ] diff --git a/panel/migrations/0266_auto_20250601_1035.py b/panel/migrations/0266_auto_20250601_1035.py new file mode 100644 index 0000000..34fa1d6 --- /dev/null +++ b/panel/migrations/0266_auto_20250601_1035.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-06-01 10:35 + +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', '0055_auto_20250601_1035'), + ('panel', '0265_auto_20250531_1633'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 709080)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 658038)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 658038)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 658038)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 658038)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 800914)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 800914)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 661550)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 661550)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 661550)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 35, 36, 661550)), + ), + 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/0267_auto_20250603_1610.py b/panel/migrations/0267_auto_20250603_1610.py new file mode 100644 index 0000000..39329b7 --- /dev/null +++ b/panel/migrations/0267_auto_20250603_1610.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2025-06-03 16:10 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0266_auto_20250601_1035'), + ] + + 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, 3, 16, 8, 57, 529682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 468896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 468896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 468896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 468896)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 669786)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 669786)), + ), + 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, 16, 8, 57, 473109)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 473109)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 473109)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 16, 8, 57, 483377)), + ), + ] diff --git a/panel/migrations/0268_auto_20250607_1633.py b/panel/migrations/0268_auto_20250607_1633.py new file mode 100644 index 0000000..66ab073 --- /dev/null +++ b/panel/migrations/0268_auto_20250607_1633.py @@ -0,0 +1,101 @@ +# Generated by Django 3.2.13 on 2025-06-07 16: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', '0267_auto_20250603_1610'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='register_date', + field=models.DateTimeField(null=True), + ), + 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, 33, 18, 554871)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 491652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 491652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 491652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 491652)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 643683)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 643683)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 495670)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 495670)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 495670)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 33, 18, 507457)), + ), + 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)), + ('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)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commonly_used_steward', to='panel.guilds')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0269_auto_20250610_1356.py b/panel/migrations/0269_auto_20250610_1356.py new file mode 100644 index 0000000..5b9958c --- /dev/null +++ b/panel/migrations/0269_auto_20250610_1356.py @@ -0,0 +1,130 @@ +# Generated by Django 3.2.13 on 2025-06-10 13:56 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0268_auto_20250607_1633'), + ] + + operations = [ + migrations.AddField( + model_name='commonlyused', + name='priority', + field=models.IntegerField(default=0), + ), + 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.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, 10, 13, 56, 4, 735451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 670178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 670178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 670178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 670178)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 832387)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 832387)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 674199)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 674199)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 674199)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 56, 4, 686004)), + ), + ] diff --git a/panel/migrations/0270_auto_20250628_1430.py b/panel/migrations/0270_auto_20250628_1430.py new file mode 100644 index 0000000..6a97f87 --- /dev/null +++ b/panel/migrations/0270_auto_20250628_1430.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-28 14:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0269_auto_20250610_1356'), + ] + + 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, 30, 15, 768819)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 721263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 721263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 721263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 721263)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 848435)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 848435)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 725279)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 725279)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 725279)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 30, 15, 736251)), + ), + ] diff --git a/panel/migrations/0271_auto_20250628_1505.py b/panel/migrations/0271_auto_20250628_1505.py new file mode 100644 index 0000000..f0597fe --- /dev/null +++ b/panel/migrations/0271_auto_20250628_1505.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-28 15:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0270_auto_20250628_1430'), + ] + + 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, 5, 29, 563575)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 627601)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 627601)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 500765)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 5, 29, 518470)), + ), + ] diff --git a/panel/migrations/0272_auto_20250707_1154.py b/panel/migrations/0272_auto_20250707_1154.py new file mode 100644 index 0000000..2fd3d4e --- /dev/null +++ b/panel/migrations/0272_auto_20250707_1154.py @@ -0,0 +1,92 @@ +# Generated by Django 3.2.13 on 2025-07-07 11: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', '0271_auto_20250628_1505'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 179984)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 99880)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 99880)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 99880)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 99880)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 280394)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 280394)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 104893)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 104893)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 104893)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 11, 54, 37, 116910)), + ), + 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)), + ('system_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/0273_auto_20250708_1044.py b/panel/migrations/0273_auto_20250708_1044.py new file mode 100644 index 0000000..11dc9b8 --- /dev/null +++ b/panel/migrations/0273_auto_20250708_1044.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-07-08 10:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0272_auto_20250707_1154'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='order_limit', + field=models.BooleanField(default=False), + ), + 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, 10, 44, 10, 343651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 268190)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 268190)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 268190)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 268190)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 419530)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 419530)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 272143)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 272143)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 272143)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 44, 10, 285996)), + ), + ] diff --git a/panel/migrations/0274_auto_20250708_1615.py b/panel/migrations/0274_auto_20250708_1615.py new file mode 100644 index 0000000..a61c147 --- /dev/null +++ b/panel/migrations/0274_auto_20250708_1615.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2025-07-08 16: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', '0273_auto_20250708_1044'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 18, 306354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 185248)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 185248)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 185248)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 185248)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 18, 383343)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 18, 383343)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 187256)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 187256)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 187256)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 16, 15, 17, 212835)), + ), + 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/0275_auto_20250709_1624.py b/panel/migrations/0275_auto_20250709_1624.py new file mode 100644 index 0000000..cec47a3 --- /dev/null +++ b/panel/migrations/0275_auto_20250709_1624.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-09 16:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0274_auto_20250708_1615'), + ] + + 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, 16, 24, 7, 164852)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 121323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 121323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 121323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 121323)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 243863)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 243863)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 123326)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 123326)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 123326)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 16, 24, 7, 135340)), + ), + ] diff --git a/panel/migrations/0276_auto_20250713_1430.py b/panel/migrations/0276_auto_20250713_1430.py new file mode 100644 index 0000000..6b364f9 --- /dev/null +++ b/panel/migrations/0276_auto_20250713_1430.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-13 14:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0275_auto_20250709_1624'), + ] + + 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, 14, 29, 54, 868384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 53, 899004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 53, 899004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 53, 899004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 53, 899004)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 55, 848741)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 55, 848741)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 54, 85676)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 54, 85676)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 54, 85676)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 14, 29, 54, 100706)), + ), + ] diff --git a/panel/migrations/0277_auto_20250714_1049.py b/panel/migrations/0277_auto_20250714_1049.py new file mode 100644 index 0000000..522f3cc --- /dev/null +++ b/panel/migrations/0277_auto_20250714_1049.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-07-14 10:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0276_auto_20250713_1430'), + ] + + 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, 49, 22, 356777)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 301665)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 301665)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 301665)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 301665)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 425736)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 425736)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 305674)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 303670)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 305674)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 49, 22, 315441)), + ), + ] diff --git a/panel/migrations/0278_auto_20250714_1102.py b/panel/migrations/0278_auto_20250714_1102.py new file mode 100644 index 0000000..47831c3 --- /dev/null +++ b/panel/migrations/0278_auto_20250714_1102.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-14 11:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0277_auto_20250714_1049'), + ] + + 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, 11, 2, 10, 355674)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 935980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 935980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 935980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 935980)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 10, 616671)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 10, 616671)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 939981)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 938980)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 938980)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 11, 2, 9, 952940)), + ), + ] diff --git a/panel/migrations/0279_auto_20250719_0909.py b/panel/migrations/0279_auto_20250719_0909.py new file mode 100644 index 0000000..6f579f7 --- /dev/null +++ b/panel/migrations/0279_auto_20250719_0909.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-19 09:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0278_auto_20250714_1102'), + ] + + 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, 9, 9, 25, 994102)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 953355)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 953355)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 953355)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 953355)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 26, 73007)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 26, 73007)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 955361)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 955361)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 955361)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 9, 25, 962385)), + ), + ] diff --git a/panel/migrations/0280_auto_20250719_0942.py b/panel/migrations/0280_auto_20250719_0942.py new file mode 100644 index 0000000..65b9cd4 --- /dev/null +++ b/panel/migrations/0280_auto_20250719_0942.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-19 09:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0279_auto_20250719_0909'), + ] + + 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, 41, 56, 689512)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 624860)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 624860)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 624860)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 624860)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 765227)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 765227)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 628827)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 628827)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 628827)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 41, 56, 640519)), + ), + ] diff --git a/panel/migrations/0281_auto_20250721_1055.py b/panel/migrations/0281_auto_20250721_1055.py new file mode 100644 index 0000000..d93a530 --- /dev/null +++ b/panel/migrations/0281_auto_20250721_1055.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2025-07-21 10: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', '0280_auto_20250719_0942'), + ] + + 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, 21, 10, 55, 0, 962864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 904170)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 904170)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 904170)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 904170)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 1, 36635)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 1, 36635)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 908172)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 907170)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 907170)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 21, 10, 55, 0, 919161)), + ), + 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/0282_auto_20250722_1259.py b/panel/migrations/0282_auto_20250722_1259.py new file mode 100644 index 0000000..552d345 --- /dev/null +++ b/panel/migrations/0282_auto_20250722_1259.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-07-22 12:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0281_auto_20250721_1055'), + ] + + operations = [ + 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, 59, 16, 512915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 454118)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 454118)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 454118)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 454118)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 584559)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 584559)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 457806)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 457806)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 457806)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 59, 16, 468805)), + ), + ] diff --git a/panel/migrations/0283_auto_20250723_1031.py b/panel/migrations/0283_auto_20250723_1031.py new file mode 100644 index 0000000..572dda3 --- /dev/null +++ b/panel/migrations/0283_auto_20250723_1031.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-07-23 10:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0282_auto_20250722_1259'), + ] + + 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.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, 31, 7, 379686)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 334128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 334128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 334128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 334128)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 457187)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 457187)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 336133)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 336133)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 336133)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 31, 7, 347902)), + ), + ] diff --git a/panel/migrations/0284_auto_20250727_0802.py b/panel/migrations/0284_auto_20250727_0802.py new file mode 100644 index 0000000..aadae6e --- /dev/null +++ b/panel/migrations/0284_auto_20250727_0802.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-07-27 08:02 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0283_auto_20250723_1031'), + ] + + 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, 8, 2, 24, 723494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 663712)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 663712)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 663712)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 663712)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 798093)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 798093)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 666712)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 666712)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 666712)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 8, 2, 24, 672058)), + ), + ] diff --git a/panel/migrations/0285_auto_20250729_1146.py b/panel/migrations/0285_auto_20250729_1146.py new file mode 100644 index 0000000..a8fed20 --- /dev/null +++ b/panel/migrations/0285_auto_20250729_1146.py @@ -0,0 +1,135 @@ +# Generated by Django 3.2.13 on 2025-07-29 11: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', '0284_auto_20250727_0802'), + ] + + 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, 29, 11, 46, 2, 453384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 394395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 394395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 394395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 394395)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 525811)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 525811)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 397396)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 397396)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 397396)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 29, 11, 46, 2, 409099)), + ), + 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, + }, + ), + 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/0286_auto_20250803_0824.py b/panel/migrations/0286_auto_20250803_0824.py new file mode 100644 index 0000000..d0039a2 --- /dev/null +++ b/panel/migrations/0286_auto_20250803_0824.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-08-03 08:24 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0285_auto_20250729_1146'), + ] + + 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, 24, 33, 743782)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 860025)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 860025)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 860025)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 860025)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 34, 503053)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 34, 503053)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 864039)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 864039)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 864039)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 24, 32, 875827)), + ), + ] diff --git a/panel/migrations/0287_auto_20250805_0855.py b/panel/migrations/0287_auto_20250805_0855.py new file mode 100644 index 0000000..d828c48 --- /dev/null +++ b/panel/migrations/0287_auto_20250805_0855.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-08-05 08:55 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0286_auto_20250803_0824'), + ] + + 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, 55, 16, 669040)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 610815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 610815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 610815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 610815)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 741006)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 741006)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 613816)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 613816)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 613816)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 55, 16, 625242)), + ), + ] diff --git a/panel/migrations/0288_auto_20250806_1157.py b/panel/migrations/0288_auto_20250806_1157.py new file mode 100644 index 0000000..aa64875 --- /dev/null +++ b/panel/migrations/0288_auto_20250806_1157.py @@ -0,0 +1,139 @@ +# Generated by Django 3.2.13 on 2025-08-06 11:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0287_auto_20250805_0855'), + ] + + 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, 6, 11, 57, 12, 948449)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 881662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 881662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 881662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 881662)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 13, 25570)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 13, 25570)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 885670)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 885670)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 885670)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 11, 57, 12, 899430)), + ), + ] diff --git a/panel/migrations/0289_auto_20250807_1008.py b/panel/migrations/0289_auto_20250807_1008.py new file mode 100644 index 0000000..e91ad2a --- /dev/null +++ b/panel/migrations/0289_auto_20250807_1008.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-08-07 10:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0288_auto_20250806_1157'), + ] + + 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, 7, 10, 8, 44, 869096)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 959216)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 959216)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 7, 10, 8, 44, 806374)), + ), + 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, 7, 10, 8, 44, 823059)), + ), + ] diff --git a/panel/migrations/0290_auto_20250809_0952.py b/panel/migrations/0290_auto_20250809_0952.py new file mode 100644 index 0000000..73e349b --- /dev/null +++ b/panel/migrations/0290_auto_20250809_0952.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-08-09 09:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0289_auto_20250807_1008'), + ] + + 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, 52, 43, 767036)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 703381)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 703381)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 703381)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 703381)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 830478)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 830478)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 719104)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 703381)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 719104)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 52, 43, 719104)), + ), + ] diff --git a/panel/migrations/0291_auto_20250809_1023.py b/panel/migrations/0291_auto_20250809_1023.py new file mode 100644 index 0000000..37c0370 --- /dev/null +++ b/panel/migrations/0291_auto_20250809_1023.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 10:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0290_auto_20250809_0952'), + ] + + 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, 23, 9, 989457)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 814557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 814557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 814557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 814557)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 10, 157195)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 10, 157195)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 818615)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 818615)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 818615)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 23, 9, 900035)), + ), + ] diff --git a/panel/migrations/0292_auto_20250809_1239.py b/panel/migrations/0292_auto_20250809_1239.py new file mode 100644 index 0000000..b731449 --- /dev/null +++ b/panel/migrations/0292_auto_20250809_1239.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 12:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0291_auto_20250809_1023'), + ] + + 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, 39, 35, 521079)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 600447)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 600447)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 473364)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 39, 35, 489159)), + ), + ] diff --git a/panel/migrations/0293_auto_20250809_1524.py b/panel/migrations/0293_auto_20250809_1524.py new file mode 100644 index 0000000..e965d87 --- /dev/null +++ b/panel/migrations/0293_auto_20250809_1524.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-08-09 15:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0292_auto_20250809_1239'), + ] + + 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.AddField( + model_name='poultryhatching', + name='archive_date', + field=models.DateTimeField(null=True), + ), + 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, 24, 29, 668981)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 603985)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 603985)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 603985)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 603985)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 738782)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 738782)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 605990)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 605990)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 605990)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 24, 29, 623776)), + ), + ] diff --git a/panel/migrations/0294_auto_20250810_1420.py b/panel/migrations/0294_auto_20250810_1420.py new file mode 100644 index 0000000..dd2de8e --- /dev/null +++ b/panel/migrations/0294_auto_20250810_1420.py @@ -0,0 +1,162 @@ +# Generated by Django 3.2.13 on 2025-08-10 14: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', '0293_auto_20250809_1524'), + ] + + operations = [ + 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.AddField( + model_name='directbuyingpayment', + name='payment_deadline_supporter_message', + field=models.TextField(null=True), + ), + 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, 20, 17, 728525)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 670283)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 670283)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 670283)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 670283)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 810957)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 810957)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 674296)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 674296)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 674296)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 20, 17, 679335)), + ), + migrations.CreateModel( + name='FinePermission', + 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)), + ('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)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='finepermission_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='finepermission_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0295_auto_20250817_0854.py b/panel/migrations/0295_auto_20250817_0854.py new file mode 100644 index 0000000..f98d29c --- /dev/null +++ b/panel/migrations/0295_auto_20250817_0854.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 08:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0294_auto_20250810_1420'), + ] + + 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, 54, 8, 267179)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 219799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 219799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 219799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 219799)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 344681)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 344681)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 223573)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 223573)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 223573)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 54, 8, 233599)), + ), + ] diff --git a/panel/migrations/0296_auto_20250817_0947.py b/panel/migrations/0296_auto_20250817_0947.py new file mode 100644 index 0000000..ee2f455 --- /dev/null +++ b/panel/migrations/0296_auto_20250817_0947.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-08-17 09: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', '0295_auto_20250817_0854'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 345360)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 236841)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 236841)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 236841)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 236841)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 512095)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 512095)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 240857)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 240857)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 240857)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 9, 47, 33, 254119)), + ), + 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/0297_auto_20250817_1031.py b/panel/migrations/0297_auto_20250817_1031.py new file mode 100644 index 0000000..2685454 --- /dev/null +++ b/panel/migrations/0297_auto_20250817_1031.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 10:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0296_auto_20250817_0947'), + ] + + 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, 31, 42, 177459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 118594)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 118594)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 118594)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 118594)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 249915)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 249915)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 121593)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 121593)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 121593)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 31, 42, 133258)), + ), + ] diff --git a/panel/migrations/0298_auto_20250817_1051.py b/panel/migrations/0298_auto_20250817_1051.py new file mode 100644 index 0000000..5bcd245 --- /dev/null +++ b/panel/migrations/0298_auto_20250817_1051.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-08-17 10:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0297_auto_20250817_1031'), + ] + + 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.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, 51, 4, 432713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 372350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 372350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 372350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 372350)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 504558)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 504558)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 375350)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 375350)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 375350)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 51, 4, 387294)), + ), + ] diff --git a/panel/migrations/0299_auto_20250817_1358.py b/panel/migrations/0299_auto_20250817_1358.py new file mode 100644 index 0000000..453f867 --- /dev/null +++ b/panel/migrations/0299_auto_20250817_1358.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 13:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0298_auto_20250817_1051'), + ] + + 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, 58, 32, 366385)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 296386)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 296386)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 296386)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 296386)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 436385)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 437417)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 300386)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 300386)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 300386)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 58, 32, 319385)), + ), + ] diff --git a/panel/migrations/0300_auto_20250818_0950.py b/panel/migrations/0300_auto_20250818_0950.py new file mode 100644 index 0000000..4598b4d --- /dev/null +++ b/panel/migrations/0300_auto_20250818_0950.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2025-08-18 09:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0299_auto_20250817_1358'), + ] + + 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, 50, 11, 75242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 24692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 24692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 24692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 24692)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 158266)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 158266)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 29248)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 29248)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 29248)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 50, 11, 40666)), + ), + ] diff --git a/panel/migrations/0301_auto_20250820_1154.py b/panel/migrations/0301_auto_20250820_1154.py new file mode 100644 index 0000000..c74dd49 --- /dev/null +++ b/panel/migrations/0301_auto_20250820_1154.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-20 11:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0300_auto_20250818_0950'), + ] + + 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, 53, 49, 625686)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 689155)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 689155)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 53, 49, 577954)), + ), + ] diff --git a/panel/migrations/0302_auto_20250825_0835.py b/panel/migrations/0302_auto_20250825_0835.py new file mode 100644 index 0000000..623b176 --- /dev/null +++ b/panel/migrations/0302_auto_20250825_0835.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-25 08:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0301_auto_20250820_1154'), + ] + + 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, 25, 8, 35, 11, 590496)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 530759)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 530759)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 530759)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 530759)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 663401)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 663401)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 534758)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 534758)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 534758)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 8, 35, 11, 545459)), + ), + ] diff --git a/panel/migrations/0303_auto_20250825_1630.py b/panel/migrations/0303_auto_20250825_1630.py new file mode 100644 index 0000000..968306b --- /dev/null +++ b/panel/migrations/0303_auto_20250825_1630.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-08-25 16:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0302_auto_20250825_0835'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='market_buying_capacity_percent_status', + field=models.BooleanField(default=False), + ), + 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.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, 30, 36, 245480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 183347)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 183347)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 183347)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 183347)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 322099)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 322099)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 186346)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 186346)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 186346)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 30, 36, 198054)), + ), + ] diff --git a/panel/migrations/0304_auto_20250826_0920.py b/panel/migrations/0304_auto_20250826_0920.py new file mode 100644 index 0000000..36195c3 --- /dev/null +++ b/panel/migrations/0304_auto_20250826_0920.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-08-26 09: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', '0303_auto_20250825_1630'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 4, 181644)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 953762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 953762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 953762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 953762)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 4, 386797)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 4, 386797)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 957760)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 957760)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 957760)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 19, 3, 969859)), + ), + 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/0305_auto_20250826_0948.py b/panel/migrations/0305_auto_20250826_0948.py new file mode 100644 index 0000000..1355758 --- /dev/null +++ b/panel/migrations/0305_auto_20250826_0948.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-26 09:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0304_auto_20250826_0920'), + ] + + 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, 47, 52, 432899)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 365586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 365586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 365586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 365586)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 526426)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 526426)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 369603)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 369603)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 369603)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 47, 52, 383407)), + ), + ] diff --git a/panel/migrations/0306_auto_20250827_1019.py b/panel/migrations/0306_auto_20250827_1019.py new file mode 100644 index 0000000..1a8bd27 --- /dev/null +++ b/panel/migrations/0306_auto_20250827_1019.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-27 10:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0305_auto_20250826_0948'), + ] + + 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, 19, 17, 579910)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 518026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 518026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 518026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 518026)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 655179)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 655179)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 521717)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 521717)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 521717)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 19, 17, 533717)), + ), + ] diff --git a/panel/migrations/0307_auto_20250827_1701.py b/panel/migrations/0307_auto_20250827_1701.py new file mode 100644 index 0000000..394a11c --- /dev/null +++ b/panel/migrations/0307_auto_20250827_1701.py @@ -0,0 +1,92 @@ +# Generated by Django 3.2.13 on 2025-08-27 17: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', '0306_auto_20250827_1019'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 753669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 697834)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 697834)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 697834)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 697834)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 836920)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 836920)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 701851)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 701851)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 701851)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 17, 1, 9, 711897)), + ), + 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/0308_auto_20250829_0153.py b/panel/migrations/0308_auto_20250829_0153.py new file mode 100644 index 0000000..8325edf --- /dev/null +++ b/panel/migrations/0308_auto_20250829_0153.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-08-29 01:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0307_auto_20250827_1701'), + ] + + 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, 53, 3, 345000)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 516956)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 516956)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 188750)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 53, 3, 220001)), + ), + ] diff --git a/panel/migrations/0309_auto_20250830_1026.py b/panel/migrations/0309_auto_20250830_1026.py new file mode 100644 index 0000000..9981882 --- /dev/null +++ b/panel/migrations/0309_auto_20250830_1026.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-30 10:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0308_auto_20250829_0153'), + ] + + 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, 10, 25, 49, 306324)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 241525)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 241525)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 241525)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 241525)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 384626)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 384626)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 245172)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 245172)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 245172)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 10, 25, 49, 257223)), + ), + ] diff --git a/panel/migrations/0310_auto_20250831_1016.py b/panel/migrations/0310_auto_20250831_1016.py new file mode 100644 index 0000000..fdacd56 --- /dev/null +++ b/panel/migrations/0310_auto_20250831_1016.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-08-31 10:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0309_auto_20250830_1026'), + ] + + 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, 10, 16, 26, 291754)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 233208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 233208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 233208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 233208)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 362792)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 362792)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 237207)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 236207)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 236207)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 10, 16, 26, 248435)), + ), + ] diff --git a/panel/migrations/0311_auto_20250901_0929.py b/panel/migrations/0311_auto_20250901_0929.py new file mode 100644 index 0000000..2f675fc --- /dev/null +++ b/panel/migrations/0311_auto_20250901_0929.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-09-01 09: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 = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0310_auto_20250831_1016'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 514323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 455804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 455804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 455804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 455804)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 571829)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 571829)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 459816)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 459816)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 459816)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 9, 28, 50, 462827)), + ), + 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/0312_auto_20250901_1650.py b/panel/migrations/0312_auto_20250901_1650.py new file mode 100644 index 0000000..924e359 --- /dev/null +++ b/panel/migrations/0312_auto_20250901_1650.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-09-01 16: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', '0056_auto_20250901_1650'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0311_auto_20250901_0929'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 13, 54128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 13, 135616)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 13, 135616)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 12, 988611)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 16, 50, 13, 6472)), + ), + 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/0313_auto_20250902_1217.py b/panel/migrations/0313_auto_20250902_1217.py new file mode 100644 index 0000000..6a13631 --- /dev/null +++ b/panel/migrations/0313_auto_20250902_1217.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-09-02 12:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0312_auto_20250901_1650'), + ] + + 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, 17, 26, 758827)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 701462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 701462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 701462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 701462)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 824069)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 824069)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 705473)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 705473)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 705473)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 17, 26, 715239)), + ), + ] diff --git a/panel/migrations/0314_auto_20250902_1659.py b/panel/migrations/0314_auto_20250902_1659.py new file mode 100644 index 0000000..5fcb6fd --- /dev/null +++ b/panel/migrations/0314_auto_20250902_1659.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-02 16:59 + +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', '0313_auto_20250902_1217'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 821278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 761864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 761864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 761864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 761864)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 884377)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 884377)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 765882)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 763872)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 763872)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 16, 59, 46, 775923)), + ), + 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/0315_auto_20250907_0855.py b/panel/migrations/0315_auto_20250907_0855.py new file mode 100644 index 0000000..1fbe597 --- /dev/null +++ b/panel/migrations/0315_auto_20250907_0855.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-09-07 08:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0314_auto_20250902_1659'), + ] + + 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, 7, 8, 55, 6, 735337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 804461)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 804461)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 7, 8, 55, 6, 672136)), + ), + 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, 7, 8, 55, 6, 688111)), + ), + ] diff --git a/panel/migrations/0316_auto_20250914_1106.py b/panel/migrations/0316_auto_20250914_1106.py new file mode 100644 index 0000000..8fcde75 --- /dev/null +++ b/panel/migrations/0316_auto_20250914_1106.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-14 11:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0315_auto_20250907_0855'), + ] + + 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, 6, 6, 381219)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 438517)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 438517)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 313104)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 6, 6, 327566)), + ), + ] diff --git a/panel/migrations/0317_auto_20250914_1455.py b/panel/migrations/0317_auto_20250914_1455.py new file mode 100644 index 0000000..c7e2085 --- /dev/null +++ b/panel/migrations/0317_auto_20250914_1455.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-14 14:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0316_auto_20250914_1106'), + ] + + 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, 55, 22, 194527)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 136300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 136300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 136300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 136300)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 264495)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 264495)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 140528)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 139299)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 140528)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 55, 22, 150527)), + ), + ] diff --git a/panel/migrations/0318_auto_20250915_0911.py b/panel/migrations/0318_auto_20250915_0911.py new file mode 100644 index 0000000..62ae28f --- /dev/null +++ b/panel/migrations/0318_auto_20250915_0911.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-15 09:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0317_auto_20250914_1455'), + ] + + 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, 11, 28, 520673)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 463557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 463557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 463557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 463557)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 589822)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 589822)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 465562)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 465562)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 465562)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 11, 28, 477339)), + ), + ] diff --git a/panel/migrations/0319_auto_20250915_1606.py b/panel/migrations/0319_auto_20250915_1606.py new file mode 100644 index 0000000..fc12750 --- /dev/null +++ b/panel/migrations/0319_auto_20250915_1606.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-09-15 16:06 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0318_auto_20250915_0911'), + ] + + 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, 6, 44, 253895)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 192081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 192081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 192081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 192081)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 334682)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 334682)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 196095)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 196095)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 196095)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 6, 44, 207881)), + ), + ] diff --git a/panel/migrations/0320_auto_20250916_0847.py b/panel/migrations/0320_auto_20250916_0847.py new file mode 100644 index 0000000..b4a2e9c --- /dev/null +++ b/panel/migrations/0320_auto_20250916_0847.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-16 08:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0319_auto_20250915_1606'), + ] + + 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)), + ('group_name', models.CharField(max_length=250)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 200540)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 143424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 143424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 143424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 143424)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 261775)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 261775)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 145431)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 145431)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 145431)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 8, 47, 3, 157214)), + ), + ] diff --git a/panel/migrations/0321_auto_20250916_0941.py b/panel/migrations/0321_auto_20250916_0941.py new file mode 100644 index 0000000..9211e41 --- /dev/null +++ b/panel/migrations/0321_auto_20250916_0941.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-16 09:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0320_auto_20250916_0847'), + ] + + 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, 40, 50, 454240)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 436156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 436156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 436156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 436156)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 50, 750834)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 50, 750834)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 793690)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 793690)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 793690)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 40, 49, 805726)), + ), + ] diff --git a/panel/migrations/0322_auto_20250916_1053.py b/panel/migrations/0322_auto_20250916_1053.py new file mode 100644 index 0000000..ace2b55 --- /dev/null +++ b/panel/migrations/0322_auto_20250916_1053.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-16 10:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0321_auto_20250916_0941'), + ] + + 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, 53, 18, 794684)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 460510)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 460510)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 460510)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 460510)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 19, 57613)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 19, 57613)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 464510)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 464510)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 464510)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 53, 18, 478917)), + ), + ] diff --git a/panel/migrations/0323_auto_20250916_1433.py b/panel/migrations/0323_auto_20250916_1433.py new file mode 100644 index 0000000..febbdc8 --- /dev/null +++ b/panel/migrations/0323_auto_20250916_1433.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-16 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0322_auto_20250916_1053'), + ] + + 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, 33, 4, 394601)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 327660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 327660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 327660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 327660)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 473571)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 473571)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 331415)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 331415)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 331415)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 33, 4, 345200)), + ), + ] diff --git a/panel/migrations/0324_auto_20250920_0949.py b/panel/migrations/0324_auto_20250920_0949.py new file mode 100644 index 0000000..edb4c05 --- /dev/null +++ b/panel/migrations/0324_auto_20250920_0949.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-09-20 09:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0323_auto_20250916_1433'), + ] + + operations = [ + migrations.AddField( + model_name='poultrysciencereport', + name='state', + field=models.CharField(default='pending', max_length=50), + ), + 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, 49, 13, 618989)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 114251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 114251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 114251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 114251)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 14, 123177)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 14, 123177)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 117047)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 117047)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 117047)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 49, 13, 130897)), + ), + ] diff --git a/panel/migrations/0325_auto_20250920_1316.py b/panel/migrations/0325_auto_20250920_1316.py new file mode 100644 index 0000000..7ef8248 --- /dev/null +++ b/panel/migrations/0325_auto_20250920_1316.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2025-09-20 13:16 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0057_auto_20250920_1316'), + ('panel', '0324_auto_20250920_0949'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 406371)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 345356)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 345356)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 345356)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 345356)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 474050)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 474050)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 348458)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 348458)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 348458)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 16, 45, 362500)), + ), + 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/0326_auto_20250922_0914.py b/panel/migrations/0326_auto_20250922_0914.py new file mode 100644 index 0000000..a93c5fb --- /dev/null +++ b/panel/migrations/0326_auto_20250922_0914.py @@ -0,0 +1,213 @@ +# Generated by Django 3.2.13 on 2025-09-22 09:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0325_auto_20250920_1316'), + ] + + 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.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.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='message_registerer_role', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='real_quantity', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='real_quantity_ai', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 493003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 434037)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 433038)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 434037)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 433038)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 564435)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 564435)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 437038)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 437038)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 437038)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 9, 13, 32, 448709)), + ), + ] diff --git a/panel/migrations/0327_auto_20250922_1054.py b/panel/migrations/0327_auto_20250922_1054.py new file mode 100644 index 0000000..fd89fa8 --- /dev/null +++ b/panel/migrations/0327_auto_20250922_1054.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-22 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0326_auto_20250922_0914'), + ] + + 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, 54, 28, 176052)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 112887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 112887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 112887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 112887)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 251823)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 251823)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 116919)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 116919)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 116919)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 54, 28, 129005)), + ), + ] diff --git a/panel/migrations/0328_auto_20250922_1350.py b/panel/migrations/0328_auto_20250922_1350.py new file mode 100644 index 0000000..d1bd130 --- /dev/null +++ b/panel/migrations/0328_auto_20250922_1350.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2025-09-22 13:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0327_auto_20250922_1054'), + ] + + 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_commitment_governmental_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, 50, 30, 890361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 836553)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 836553)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 836553)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 836553)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 983219)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 983219)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 840585)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 840585)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 840585)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 50, 30, 852967)), + ), + ] diff --git a/panel/migrations/0329_auto_20250924_1349.py b/panel/migrations/0329_auto_20250924_1349.py new file mode 100644 index 0000000..a7f2e97 --- /dev/null +++ b/panel/migrations/0329_auto_20250924_1349.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-09-24 13:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0328_auto_20250922_1350'), + ] + + 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, 49, 38, 355701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 157898)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 157898)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 157898)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 157898)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 607129)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 607129)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 163672)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 163672)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 163672)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 49, 38, 233042)), + ), + ] diff --git a/panel/migrations/0330_auto_20250924_1430.py b/panel/migrations/0330_auto_20250924_1430.py new file mode 100644 index 0000000..73aadde --- /dev/null +++ b/panel/migrations/0330_auto_20250924_1430.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2025-09-24 14:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0329_auto_20250924_1349'), + ] + + 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, 30, 13, 92270)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 169905)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 169905)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 44485)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 30, 13, 60338)), + ), + ] diff --git a/panel/migrations/0331_auto_20250925_1052.py b/panel/migrations/0331_auto_20250925_1052.py new file mode 100644 index 0000000..f78f2df --- /dev/null +++ b/panel/migrations/0331_auto_20250925_1052.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-25 10:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0330_auto_20250924_1430'), + ] + + 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, 51, 28, 308803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 579825)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 579825)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 142660)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 51, 28, 176428)), + ), + ] diff --git a/panel/migrations/0332_auto_20250925_1109.py b/panel/migrations/0332_auto_20250925_1109.py new file mode 100644 index 0000000..d5f122a --- /dev/null +++ b/panel/migrations/0332_auto_20250925_1109.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-25 11:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0331_auto_20250925_1052'), + ] + + 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, 8, 47, 639864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 48, 339976)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 48, 339976)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 389863)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 8, 47, 452372)), + ), + ] diff --git a/panel/migrations/0333_auto_20250925_1659.py b/panel/migrations/0333_auto_20250925_1659.py new file mode 100644 index 0000000..2e67918 --- /dev/null +++ b/panel/migrations/0333_auto_20250925_1659.py @@ -0,0 +1,154 @@ +# Generated by Django 3.2.13 on 2025-09-25 16:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0332_auto_20250925_1109'), + ] + + 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_remain_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_remain_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='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.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, 16, 59, 12, 400061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 327061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 327061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 327061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 327061)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 499059)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 499059)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 331061)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 331061)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 331061)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 16, 59, 12, 344061)), + ), + ] diff --git a/panel/migrations/0334_auto_20250927_2226.py b/panel/migrations/0334_auto_20250927_2226.py new file mode 100644 index 0000000..daac264 --- /dev/null +++ b/panel/migrations/0334_auto_20250927_2226.py @@ -0,0 +1,105 @@ +# Generated by Django 3.2.13 on 2025-09-27 22: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', '0333_auto_20250925_1659'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='active_expire_date_time', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardallocation', + name='expire_date_time_registration_code', + field=models.DateTimeField(null=True), + ), + 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, 22, 26, 42, 552168)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 480765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 480765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 480765)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 480765)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 607339)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 607339)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 498799)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 498799)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 498799)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 22, 26, 42, 498799)), + ), + 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)), + ('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='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/0335_auto_20250929_1508.py b/panel/migrations/0335_auto_20250929_1508.py new file mode 100644 index 0000000..ad9fc83 --- /dev/null +++ b/panel/migrations/0335_auto_20250929_1508.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-29 15:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0334_auto_20250927_2226'), + ] + + 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, 7, 42, 685461)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 448456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 447456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 447456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 447456)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 861457)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 861457)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 452456)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 452456)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 452456)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 7, 42, 472454)), + ), + ] diff --git a/panel/migrations/0336_auto_20251001_0930.py b/panel/migrations/0336_auto_20251001_0930.py new file mode 100644 index 0000000..2933f4c --- /dev/null +++ b/panel/migrations/0336_auto_20251001_0930.py @@ -0,0 +1,121 @@ +# Generated by Django 3.2.13 on 2025-10-01 09:30 + +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', '0335_auto_20250929_1508'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='active_register_code', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='expire_time_register_code', + field=models.DateTimeField(null=True), + ), + 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.AddField( + model_name='guilds', + name='register_date_register_code', + field=models.DateTimeField(null=True), + ), + 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, 10, 1, 9, 30, 17, 700982)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 647981)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 647981)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 647981)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 647981)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 764950)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 764950)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 650982)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 650982)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 650982)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 9, 30, 17, 660984)), + ), + 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/0337_auto_20251001_1131.py b/panel/migrations/0337_auto_20251001_1131.py new file mode 100644 index 0000000..cb4dbcd --- /dev/null +++ b/panel/migrations/0337_auto_20251001_1131.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-01 11:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0336_auto_20251001_0930'), + ] + + 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, 29, 55, 484124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 139675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 139675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 139675)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 139675)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 618260)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 618260)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 146671)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 145673)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 145673)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 29, 55, 393605)), + ), + ] diff --git a/panel/migrations/0338_auto_20251004_1109.py b/panel/migrations/0338_auto_20251004_1109.py new file mode 100644 index 0000000..03b325a --- /dev/null +++ b/panel/migrations/0338_auto_20251004_1109.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-10-04 11:09 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0337_auto_20251001_1131'), + ] + + 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, 8, 47, 105423)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 948608)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 948608)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 948608)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 948608)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 47, 337900)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 47, 337900)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 952614)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 952614)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 952614)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 8, 46, 966375)), + ), + ] diff --git a/panel/migrations/0339_auto_20251005_1501.py b/panel/migrations/0339_auto_20251005_1501.py new file mode 100644 index 0000000..541c046 --- /dev/null +++ b/panel/migrations/0339_auto_20251005_1501.py @@ -0,0 +1,390 @@ +# Generated by Django 3.2.13 on 2025-10-05 15: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', '0338_auto_20251004_1109'), + ] + + 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, 15, 1, 6, 971483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 7, 45723)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 7, 45723)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 895590)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 15, 1, 6, 912268)), + ), + 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/0340_auto_20251006_0851.py b/panel/migrations/0340_auto_20251006_0851.py new file mode 100644 index 0000000..cd19f88 --- /dev/null +++ b/panel/migrations/0340_auto_20251006_0851.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-06 08:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0339_auto_20251005_1501'), + ] + + 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, 51, 10, 675012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 616850)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 616850)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 616850)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 616850)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 746869)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 746869)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 619951)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 619951)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 619951)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 51, 10, 630261)), + ), + ] diff --git a/panel/migrations/0341_auto_20251006_0908.py b/panel/migrations/0341_auto_20251006_0908.py new file mode 100644 index 0000000..181d895 --- /dev/null +++ b/panel/migrations/0341_auto_20251006_0908.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-06 09:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0340_auto_20251006_0851'), + ] + + 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, 8, 13, 213869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 81408)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 81408)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 81408)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 81408)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 411048)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 411048)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 87145)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 87145)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 87145)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 8, 13, 99112)), + ), + ] diff --git a/panel/migrations/0342_auto_20251006_1459.py b/panel/migrations/0342_auto_20251006_1459.py new file mode 100644 index 0000000..a7e7d7f --- /dev/null +++ b/panel/migrations/0342_auto_20251006_1459.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-06 14:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0341_auto_20251006_0908'), + ] + + 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, 59, 20, 774119)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 715149)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 715149)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 715149)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 715149)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 845927)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 845927)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 718777)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 718777)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 718777)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 59, 20, 729095)), + ), + ] diff --git a/panel/migrations/0343_auto_20251007_1522.py b/panel/migrations/0343_auto_20251007_1522.py new file mode 100644 index 0000000..d38803a --- /dev/null +++ b/panel/migrations/0343_auto_20251007_1522.py @@ -0,0 +1,111 @@ +# Generated by Django 3.2.13 on 2025-10-07 15: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', '0342_auto_20251006_1459'), + ] + + 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.AddField( + model_name='stewardallocation', + name='steward_warehouse', + field=models.BooleanField(default=True), + ), + 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, 15, 22, 15, 974428)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 914486)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 914486)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 914486)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 914486)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 16, 46330)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 16, 46330)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 918041)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 918041)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 918041)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 22, 15, 929106)), + ), + 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/0344_auto_20251007_1646.py b/panel/migrations/0344_auto_20251007_1646.py new file mode 100644 index 0000000..28ce8c0 --- /dev/null +++ b/panel/migrations/0344_auto_20251007_1646.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-07 16:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0343_auto_20251007_1522'), + ] + + 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, 16, 46, 10, 505905)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 616249)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 616249)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 458767)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 16, 46, 10, 473753)), + ), + ] diff --git a/panel/migrations/0345_auto_20251008_1416.py b/panel/migrations/0345_auto_20251008_1416.py new file mode 100644 index 0000000..b8f9f6c --- /dev/null +++ b/panel/migrations/0345_auto_20251008_1416.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-08 14:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0344_auto_20251007_1646'), + ] + + 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, 14, 16, 15, 727682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 667203)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 667203)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 667203)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 667203)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 797574)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 797574)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 670195)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 670195)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 670195)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 14, 16, 15, 681863)), + ), + ] diff --git a/panel/migrations/0346_auto_20251012_1702.py b/panel/migrations/0346_auto_20251012_1702.py new file mode 100644 index 0000000..5186893 --- /dev/null +++ b/panel/migrations/0346_auto_20251012_1702.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-12 17:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0345_auto_20251008_1416'), + ] + + 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, 17, 2, 5, 14103)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 953528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 953528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 953528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 953528)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 5, 89768)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 5, 89768)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 957583)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 957583)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 957583)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 17, 2, 4, 967977)), + ), + ] diff --git a/panel/migrations/0347_auto_20251021_1631.py b/panel/migrations/0347_auto_20251021_1631.py new file mode 100644 index 0000000..2d545be --- /dev/null +++ b/panel/migrations/0347_auto_20251021_1631.py @@ -0,0 +1,229 @@ +# Generated by Django 3.2.13 on 2025-10-21 16: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', '0346_auto_20251012_1702'), + ] + + 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.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, 16, 31, 27, 31636)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 973586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 973586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 973586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 973586)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 27, 106698)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 27, 106698)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 976679)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 976679)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 976679)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 16, 31, 26, 987328)), + ), + 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, + }, + ), + 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)), + ('distribution_type', models.CharField(default='KillHouse', max_length=50)), + ('out', models.BooleanField(default=False)), + ('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, + }, + ), + 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/0348_auto_20251022_1621.py b/panel/migrations/0348_auto_20251022_1621.py new file mode 100644 index 0000000..21248c8 --- /dev/null +++ b/panel/migrations/0348_auto_20251022_1621.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-22 16:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0347_auto_20251021_1631'), + ] + + 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, 16, 21, 24, 839967)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 757815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 757815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 757815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 757815)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 919694)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 919694)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 761807)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 761807)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 761807)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 16, 21, 24, 779756)), + ), + ] diff --git a/panel/migrations/0349_auto_20251025_1622.py b/panel/migrations/0349_auto_20251025_1622.py new file mode 100644 index 0000000..8270bfb --- /dev/null +++ b/panel/migrations/0349_auto_20251025_1622.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2025-10-25 16:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0348_auto_20251022_1621'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='distribution_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='production_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='possegmentation', + name='distribution_type', + field=models.CharField(max_length=20, 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='distribution_type', + field=models.CharField(max_length=20, 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, 16, 21, 50, 311604)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 251879)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 251879)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 251879)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 251879)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 382301)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 382301)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 255067)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 255067)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 255067)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 16, 21, 50, 266070)), + ), + ] diff --git a/panel/migrations/0350_auto_20251026_2130.py b/panel/migrations/0350_auto_20251026_2130.py new file mode 100644 index 0000000..b5df697 --- /dev/null +++ b/panel/migrations/0350_auto_20251026_2130.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-26 21:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0349_auto_20251025_1622'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='expire_time_ten_minute', + field=models.DateTimeField(null=True), + ), + 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, 21, 30, 9, 330161)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 276062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 276062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 276062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 276062)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 397693)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 397693)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 278617)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 278617)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 278617)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 21, 30, 9, 289211)), + ), + ] diff --git a/panel/migrations/0351_auto_20251027_1526.py b/panel/migrations/0351_auto_20251027_1526.py new file mode 100644 index 0000000..ce212ec --- /dev/null +++ b/panel/migrations/0351_auto_20251027_1526.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-10-27 15:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0350_auto_20251026_2130'), + ] + + 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.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, 15, 26, 1, 697825)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 629084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 629084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 629084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 629084)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 783762)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 783762)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 632595)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 632595)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 632595)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 15, 26, 1, 645725)), + ), + ] diff --git a/panel/migrations/0352_auto_20251028_1151.py b/panel/migrations/0352_auto_20251028_1151.py new file mode 100644 index 0000000..50f1b2a --- /dev/null +++ b/panel/migrations/0352_auto_20251028_1151.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-28 11:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0351_auto_20251027_1526'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequestquarantinecode', + name='traffic_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, 11, 50, 50, 110608)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 204058)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 204058)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 50358)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 11, 50, 50, 63515)), + ), + ] diff --git a/panel/migrations/0353_auto_20251028_1415.py b/panel/migrations/0353_auto_20251028_1415.py new file mode 100644 index 0000000..a137a7b --- /dev/null +++ b/panel/migrations/0353_auto_20251028_1415.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-28 14:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0352_auto_20251028_1151'), + ] + + 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, 14, 15, 29, 742456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 662168)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 662168)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 662168)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 662168)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 848068)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 848068)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 668711)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 668711)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 668711)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 14, 15, 29, 680738)), + ), + ] diff --git a/panel/migrations/0354_auto_20251029_1138.py b/panel/migrations/0354_auto_20251029_1138.py new file mode 100644 index 0000000..2cbd00e --- /dev/null +++ b/panel/migrations/0354_auto_20251029_1138.py @@ -0,0 +1,101 @@ +# Generated by Django 3.2.13 on 2025-10-29 11: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', '0353_auto_20251028_1415'), + ] + + 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, 11, 38, 17, 680608)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 629278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 629278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 629278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 629278)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 741439)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 741439)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 631277)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 631277)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 631277)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 38, 17, 642143)), + ), + 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)), + ('start_time', models.TimeField(blank=True, null=True)), + ('end_time', models.TimeField(blank=True, 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/0355_auto_20251029_1715.py b/panel/migrations/0355_auto_20251029_1715.py new file mode 100644 index 0000000..6faa3bb --- /dev/null +++ b/panel/migrations/0355_auto_20251029_1715.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-29 17:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0354_auto_20251029_1138'), + ] + + 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, 17, 14, 39, 548261)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 58545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 58545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 58545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 58545)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 638119)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 638119)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 74599)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 74599)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 74599)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 17, 14, 39, 492045)), + ), + ] diff --git a/panel/migrations/0356_auto_20251102_1538.py b/panel/migrations/0356_auto_20251102_1538.py new file mode 100644 index 0000000..f107352 --- /dev/null +++ b/panel/migrations/0356_auto_20251102_1538.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-11-02 15: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', '0355_auto_20251029_1715'), + ] + + 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, 15, 38, 41, 632030)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 564462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 564462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 564462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 564462)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 710954)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 710954)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 568003)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 568003)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 568003)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 15, 38, 41, 580832)), + ), + 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/0357_auto_20251102_1626.py b/panel/migrations/0357_auto_20251102_1626.py new file mode 100644 index 0000000..8c414b8 --- /dev/null +++ b/panel/migrations/0357_auto_20251102_1626.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-02 16:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0356_auto_20251102_1538'), + ] + + 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, 25, 46, 988950)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 926663)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 926663)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 926663)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 926663)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 47, 62785)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 47, 62785)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 929832)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 929832)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 929832)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 25, 46, 940856)), + ), + ] diff --git a/panel/migrations/0358_auto_20251102_2057.py b/panel/migrations/0358_auto_20251102_2057.py new file mode 100644 index 0000000..803face --- /dev/null +++ b/panel/migrations/0358_auto_20251102_2057.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-11-02 20:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0357_auto_20251102_1626'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 652309)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 554310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 554310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 554310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 554310)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 755314)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 755314)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 560313)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 560313)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 560313)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 57, 20, 580310)), + ), + ] diff --git a/panel/migrations/0359_auto_20251102_2058.py b/panel/migrations/0359_auto_20251102_2058.py new file mode 100644 index 0000000..1818d78 --- /dev/null +++ b/panel/migrations/0359_auto_20251102_2058.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-11-02 20:58 + +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', '0358_auto_20251102_2057'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 655857)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 597887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 597887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 597887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 597887)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 725857)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 725857)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 600888)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 600888)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 600888)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 58, 11, 610891)), + ), + 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, null=True)), + ('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/0360_auto_20251103_1458.py b/panel/migrations/0360_auto_20251103_1458.py new file mode 100644 index 0000000..b9fda10 --- /dev/null +++ b/panel/migrations/0360_auto_20251103_1458.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-11-03 14:58 + +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', '0359_auto_20251102_2058'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 496561)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 575403)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 575403)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 57, 58, 449097)), + ), + 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/0361_auto_20251103_1642.py b/panel/migrations/0361_auto_20251103_1642.py new file mode 100644 index 0000000..38e9978 --- /dev/null +++ b/panel/migrations/0361_auto_20251103_1642.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-11-03 16:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0360_auto_20251103_1458'), + ] + + 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, 16, 41, 48, 696713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 620839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 620839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 620839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 620839)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 775163)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 775163)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 637126)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 637126)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 637126)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 16, 41, 48, 647593)), + ), + ] diff --git a/panel/migrations/0362_auto_20251104_1658.py b/panel/migrations/0362_auto_20251104_1658.py new file mode 100644 index 0000000..5f737b5 --- /dev/null +++ b/panel/migrations/0362_auto_20251104_1658.py @@ -0,0 +1,114 @@ +# Generated by Django 3.2.13 on 2025-11-04 16:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0361_auto_20251103_1642'), + ] + + 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, 16, 57, 32, 726318)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 219631)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 219631)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 219631)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 219631)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 33, 971200)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 33, 972201)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 338629)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 338629)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 338629)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 16, 57, 31, 351629)), + ), + ] diff --git a/panel/migrations/0363_auto_20251105_1113.py b/panel/migrations/0363_auto_20251105_1113.py new file mode 100644 index 0000000..c1d6218 --- /dev/null +++ b/panel/migrations/0363_auto_20251105_1113.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-11-05 11:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0362_auto_20251104_1658'), + ] + + 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, 13, 31, 252515)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 190358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 190358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 190358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 190358)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 326655)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 326655)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 193358)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 193358)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 193358)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 13, 31, 204981)), + ), + ] diff --git a/panel/migrations/0364_auto_20251109_1516.py b/panel/migrations/0364_auto_20251109_1516.py new file mode 100644 index 0000000..beb132c --- /dev/null +++ b/panel/migrations/0364_auto_20251109_1516.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2025-11-09 15:16 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0363_auto_20251105_1113'), + ] + + operations = [ + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='national_id', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='national_id', + field=models.CharField(max_length=200, null=True), + ), + 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, 15, 16, 35, 205638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 133930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 133930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 133930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 133930)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 291867)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 291867)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 137948)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 137948)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 137948)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 15, 16, 35, 151744)), + ), + ] diff --git a/panel/migrations/0365_auto_20251110_1124.py b/panel/migrations/0365_auto_20251110_1124.py new file mode 100644 index 0000000..4380e46 --- /dev/null +++ b/panel/migrations/0365_auto_20251110_1124.py @@ -0,0 +1,148 @@ +# Generated by Django 3.2.13 on 2025-11-10 11: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', '0364_auto_20251109_1516'), + ] + + 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, 24, 22, 285132)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 218870)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 218870)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 218870)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 218870)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 358733)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 358733)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 221862)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 221862)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 221862)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 24, 22, 234185)), + ), + 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/0366_auto_20251111_0941.py b/panel/migrations/0366_auto_20251111_0941.py new file mode 100644 index 0000000..cc9fbd2 --- /dev/null +++ b/panel/migrations/0366_auto_20251111_0941.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-11-11 09: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', '0365_auto_20251110_1124'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 419546)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 489542)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 489542)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 357599)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 9, 40, 42, 371581)), + ), + 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/0367_auto_20251111_1619.py b/panel/migrations/0367_auto_20251111_1619.py new file mode 100644 index 0000000..539ce23 --- /dev/null +++ b/panel/migrations/0367_auto_20251111_1619.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-11 16:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0366_auto_20251111_0941'), + ] + + 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, 16, 19, 39, 592592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 530567)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 530567)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 530567)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 530567)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 663476)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 663476)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 533567)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 533567)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 533567)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 16, 19, 39, 548191)), + ), + ] diff --git a/panel/migrations/0368_auto_20251115_1513.py b/panel/migrations/0368_auto_20251115_1513.py new file mode 100644 index 0000000..74579f9 --- /dev/null +++ b/panel/migrations/0368_auto_20251115_1513.py @@ -0,0 +1,142 @@ +# Generated by Django 3.2.13 on 2025-11-15 15: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', '0367_auto_20251111_1619'), + ] + + 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, 12, 47, 814398)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 893458)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 893458)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 751291)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 12, 47, 769119)), + ), + 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/0369_auto_20251116_1609.py b/panel/migrations/0369_auto_20251116_1609.py new file mode 100644 index 0000000..a8ac9d7 --- /dev/null +++ b/panel/migrations/0369_auto_20251116_1609.py @@ -0,0 +1,329 @@ +# Generated by Django 3.2.13 on 2025-11-16 16:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0368_auto_20251115_1513'), + ] + + 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, 16, 16, 8, 52, 851230)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 778738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 778738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 778738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 778738)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 958453)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 958453)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 782581)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 782581)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 782581)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 16, 8, 52, 797910)), + ), + ] diff --git a/panel/migrations/0370_auto_20251125_1625.py b/panel/migrations/0370_auto_20251125_1625.py new file mode 100644 index 0000000..01c222a --- /dev/null +++ b/panel/migrations/0370_auto_20251125_1625.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2025-11-25 16:25 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0369_auto_20251116_1609'), + ] + + 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.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, 16, 24, 49, 67392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 557937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 557937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 557937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 557937)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 49, 186956)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 49, 186956)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 561956)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 561956)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 561956)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 16, 24, 48, 578896)), + ), + ] diff --git a/panel/migrations/0371_auto_20251130_1614.py b/panel/migrations/0371_auto_20251130_1614.py new file mode 100644 index 0000000..1f04f7b --- /dev/null +++ b/panel/migrations/0371_auto_20251130_1614.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-30 16:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0370_auto_20251125_1625'), + ] + + 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, 16, 14, 17, 119464)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 183061)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 183061)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 55586)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 16, 14, 17, 71481)), + ), + ] diff --git a/panel/migrations/0372_auto_20251202_1604.py b/panel/migrations/0372_auto_20251202_1604.py new file mode 100644 index 0000000..e4c2634 --- /dev/null +++ b/panel/migrations/0372_auto_20251202_1604.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-12-02 16:04 + +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_20251130_1614'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 274539)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 224650)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 224650)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 224650)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 224650)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 353630)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 353630)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 226654)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 226654)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 226654)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 16, 3, 50, 238687)), + ), + 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/0373_auto_20251203_1610.py b/panel/migrations/0373_auto_20251203_1610.py new file mode 100644 index 0000000..8bd72e4 --- /dev/null +++ b/panel/migrations/0373_auto_20251203_1610.py @@ -0,0 +1,100 @@ +# Generated by Django 3.2.13 on 2025-12-03 16: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', '0372_auto_20251202_1604'), + ] + + 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, 9, 54, 537512)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 470434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 470434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 470434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 470434)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 618848)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 619874)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 474267)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 474267)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 474267)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 9, 54, 488450)), + ), + 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/0374_auto_20251208_1019.py b/panel/migrations/0374_auto_20251208_1019.py new file mode 100644 index 0000000..f9a8a0c --- /dev/null +++ b/panel/migrations/0374_auto_20251208_1019.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-12-08 10:19 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0059_auto_20251208_1019'), + ('panel', '0373_auto_20251203_1610'), + ] + + 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, 10, 16, 51, 510925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 395300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 395300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 395300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 395300)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 600099)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 600099)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 413035)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 412201)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 412201)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 10, 16, 51, 452066)), + ), + ] diff --git a/panel/migrations/0375_auto_20251213_1627.py b/panel/migrations/0375_auto_20251213_1627.py new file mode 100644 index 0000000..f2bd730 --- /dev/null +++ b/panel/migrations/0375_auto_20251213_1627.py @@ -0,0 +1,197 @@ +# Generated by Django 3.2.13 on 2025-12-13 16: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 = [ + ('authentication', '0060_auto_20251213_1627'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0374_auto_20251208_1019'), + ] + + 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, 27, 37, 454576)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 394441)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 394441)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 394441)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 394441)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 530182)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 530182)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 398817)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 398817)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 398817)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 27, 37, 409788)), + ), + 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/0376_auto_20251214_2351.py b/panel/migrations/0376_auto_20251214_2351.py new file mode 100644 index 0000000..661901c --- /dev/null +++ b/panel/migrations/0376_auto_20251214_2351.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-12-14 23:51 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0061_auto_20251214_2351'), + ('panel', '0375_auto_20251213_1627'), + ] + + 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, 23, 51, 25, 940941)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 888130)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 888070)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 888114)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 888095)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 26, 8005)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 26, 8018)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 890887)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 890829)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 890841)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 23, 51, 25, 901918)), + ), + ] diff --git a/panel/migrations/0377_auto_20251215_1644.py b/panel/migrations/0377_auto_20251215_1644.py new file mode 100644 index 0000000..3ed91dc --- /dev/null +++ b/panel/migrations/0377_auto_20251215_1644.py @@ -0,0 +1,117 @@ +# Generated by Django 3.2.13 on 2025-12-15 16: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', '0376_auto_20251214_2351'), + ] + + 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, 43, 31, 619394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 341573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 341573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 341573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 341573)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 32, 146706)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 32, 146706)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 619316)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 619316)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 30, 619316)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 43, 31, 4350)), + ), + 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/0378_auto_20251216_1641.py b/panel/migrations/0378_auto_20251216_1641.py new file mode 100644 index 0000000..4b43205 --- /dev/null +++ b/panel/migrations/0378_auto_20251216_1641.py @@ -0,0 +1,147 @@ +# Generated by Django 3.2.13 on 2025-12-16 16:41 + +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', '0377_auto_20251215_1644'), + ] + + 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, 40, 15, 201534)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 280973)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 280973)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 153497)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 40, 15, 169523)), + ), + 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/0379_auto_20251217_1642.py b/panel/migrations/0379_auto_20251217_1642.py new file mode 100644 index 0000000..d00be61 --- /dev/null +++ b/panel/migrations/0379_auto_20251217_1642.py @@ -0,0 +1,436 @@ +# Generated by Django 3.2.13 on 2025-12-17 16:42 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0062_auto_20251217_1642'), + ('panel', '0378_auto_20251216_1641'), + ] + + 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, 42, 16, 253039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 182141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 182141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 182141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 182141)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 342202)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 342202)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 186714)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 186714)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 186714)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 42, 16, 199806)), + ), + ] diff --git a/panel/migrations/0380_auto_20251221_1049.py b/panel/migrations/0380_auto_20251221_1049.py new file mode 100644 index 0000000..4c64a2d --- /dev/null +++ b/panel/migrations/0380_auto_20251221_1049.py @@ -0,0 +1,180 @@ +# Generated by Django 3.2.13 on 2025-12-21 10:49 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0379_auto_20251217_1642'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='guilds_stewards', + field=models.ManyToManyField(blank=True, null=True, related_name='guilds_direct_stewards', to='panel.Steward'), + ), + migrations.AddField( + model_name='limitationfordirectpurchaseandbarinformation', + name='allow_buying', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='steward', + name='company_identifier', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='steward', + name='company_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='steward', + name='has_inquiry', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='has_partner', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='is_foreign_national', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='is_real_person', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='steward', + name='kill_house', + field=models.ManyToManyField(blank=True, null=True, related_name='stewards_kill_houses', to='panel.KillHouse'), + ), + migrations.AddField( + model_name='steward', + name='license_expire_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='steward', + name='license_issue_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='steward', + name='license_status', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='steward', + name='license_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='steward', + name='name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='steward', + name='national_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='steward', + name='phone_number', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='steward', + name='union_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='stewards', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_stewards', to='panel.steward'), + ), + migrations.AddField( + model_name='stewardallocation', + name='to_stewards', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='to_allocation_to_stewards', to='panel.steward'), + ), + migrations.AddField( + model_name='warehousearchive', + name='stewards', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewards_archive', to='panel.steward'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 657288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 594256)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 594256)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 594256)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 594256)), + ), + migrations.AlterField( + model_name='posaccesslevel', + name='pos', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='access_levels', to='panel.posmachine'), + ), + migrations.AlterField( + model_name='posauditlog', + name='action', + field=models.CharField(choices=[('CHANGE_OWNER', 'تغییر مالک'), ('CHANGE_CURRENT_DISPENSER', 'تغییر توزیع کننده'), ('CHANGE_CURRENT_REPRESENTATIVE', 'تغییر نماینده'), ('ACCESSLEVEL_UPDATE', 'بروزرسانی سطح دسترسی')], max_length=50), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 742263)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 742263)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 598261)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 598261)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 598261)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 21, 10, 48, 46, 611257)), + ), + ] 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..5e1b4c5 --- /dev/null +++ b/panel/models.py @@ -0,0 +1,7484 @@ +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 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 + ) + kill_house = models.ManyToManyField( + KillHouse, + related_name='stewards_kill_houses', + null=True, blank=True) + name = models.CharField(max_length=200,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) + 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) # حقیقی یا حقوقی + + # 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 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) + guilds_stewards = models.ManyToManyField( + Steward, + related_name='guilds_direct_stewards', + 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 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 + ) + stewards = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="allocation_to_stewards", + null=True + ) + to_stewards = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="to_allocation_to_stewards", + 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', null=True) + 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_DISPENSER', 'تغییر توزیع کننده'), + ('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) + allow_buying = models.BooleanField(default=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) + stewards = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="stewards_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..34bf8de --- /dev/null +++ b/panel/pos_helper.py @@ -0,0 +1,264 @@ +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": "Hamadan", + "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": "Hamadan", + } + 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": "Hamadan", + "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..678a15a --- /dev/null +++ b/panel/templatetags/jalali_filters.py @@ -0,0 +1,64 @@ +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): + string = str(value).strip() + + date_formats = [ + '%Y-%m-%dT%H:%M:%S.%fZ', + '%Y-%m-%dT%H:%M:%SZ', + '%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' + ] + try: + for fmt in date_formats: + try: + + value=datetime.strptime(string, fmt).date() + return shamsi_date(value,in_value=True) + except ValueError: + continue + 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..b541f91 --- /dev/null +++ b/panel/urls.py @@ -0,0 +1,1397 @@ +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, send_kill_house_debt_report_pdf_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, kill_house_debt_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, \ + fetch_evacuation_details_for_unknown_hatchings +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), + path('fetch_evacuation_details_for_unknown_hatchings/', fetch_evacuation_details_for_unknown_hatchings), + path('kdp/', kill_house_debt_report_pdf), + path('send_kill_house_debt_report_pdf_sms_manual/', send_kill_house_debt_report_pdf_sms_manual), + + +] + 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..8827044 --- /dev/null +++ b/pdf/views.py @@ -0,0 +1,1635 @@ +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.helpers import get_finance_info, check_kill_house_remain_limitation_weight +from django.db.models import F +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, KillHousePurchaseRequest, InternalTransaction, PosSegmentation, WarehouseArchive, \ + Guilds, StewardFreeBarInformation, StewardFreeSaleBarInformation +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 + + +def kill_house_debt_report_pdf(request): + font_config = FontConfiguration() + + kill_houses = KillHouse.objects.filter( + trash=False, + out_province=False + ).select_related('kill_house_operator__user', 'system_address').order_by('name') + kill_house_data = [] + production_date = (datetime.datetime.now() - datetime.timedelta(days=3)).date() + yesterday = (datetime.datetime.now() - datetime.timedelta(days=1)).date() + + for kill_house in kill_houses: + ware_house_lock = False + 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 + + if not ware_house_lock: + continue + + 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' + ) + + archives = WarehouseArchive.objects.filter( + kill_house=kill_house, + date__date=production_date, + quota='governmental', + trash=False + ) + + live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + 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_governmental_weight = archives.aggregate(total=Sum('weight'))['total'] or 0 + + total_output = kill_house_allocations_weight + kill_house_free_sale_bars_weight + segmentation_weight + archives_governmental_weight + total_remain = kill_house_requests_weight - total_output + + nature = 'کشتارکن' if kill_house.killer else 'کشتارگاه' + name_with_phone = f"{kill_house.name} ({kill_house.kill_house_operator.user.mobile or '-'})" + city = kill_house.city_name or (kill_house.system_address.city if kill_house.system_address else '-') + + kill_house_data.append({ + 'nature': nature, + 'name_with_phone': name_with_phone, + 'city': city, + 'live_weight': to_locale_str(int(live_weight)), + 'carcass_weight': to_locale_str(int(kill_house_requests_weight)), + 'distribution_weight': to_locale_str(int(total_output)), + 'remain_weight': to_locale_str(int(total_remain)), + }) + + guild_ids = list(Guilds.objects.filter(trash=False, steward=True, active=True).values_list('id', flat=True)) + + if guild_ids: + input_allocations_data = StewardAllocation.objects.filter( + to_steward_id__in=guild_ids, + date__date=yesterday, + trash=False, + receiver_state='accepted', + warehouse=True, + steward_warehouse=True, + ).values('to_steward_id').annotate(total=Sum('real_weight_of_carcasses')) + + input_free_bars_data = StewardFreeBarInformation.objects.filter( + steward_id__in=guild_ids, + date__date=yesterday, + trash=False, + warehouse=True, + ).values('steward_id').annotate(total=Sum('weight_of_carcasses')) + + output_allocations_data = StewardAllocation.objects.filter( + steward_id__in=guild_ids, + production_date__date=yesterday, + trash=False, + receiver_state__in=('pending', 'accepted'), + warehouse=True, + steward_warehouse=True, + ).values('steward_id').annotate(total=Sum('real_weight_of_carcasses')) + + free_sale_bars_data = StewardFreeSaleBarInformation.objects.filter( + steward_id__in=guild_ids, + production_date__date=yesterday, + trash=False, + warehouse=True, + ).values('steward_id').annotate(total=Sum('weight_of_carcasses')) + + input_weights = {item['to_steward_id']: item['total'] or 0 for item in input_allocations_data} + input_free_bar_weights = {item['steward_id']: item['total'] or 0 for item in input_free_bars_data} + output_allocations_weights = {item['steward_id']: item['total'] or 0 for item in output_allocations_data} + free_sale_bars_weights = {item['steward_id']: item['total'] or 0 for item in free_sale_bars_data} + + guilds = Guilds.objects.filter(id__in=guild_ids).select_related('user') + steward_data = [] + + for guild in guilds: + guild_id = guild.id + total_input = (input_weights.get(guild_id, 0) + input_free_bar_weights.get(guild_id, 0)) + total_output = (output_allocations_weights.get(guild_id, 0) + free_sale_bars_weights.get(guild_id, 0)) + remain_weight = total_input - total_output + + if total_output == 0 and total_input > 0: + unit_name = guild.guilds_name or '-' + user_fullname = guild.user.fullname if guild.user else '-' + user_phone = guild.user.mobile if guild.user else (guild.phone or '-') + name_with_phone = f"{user_fullname} ({user_phone})" + + steward_data.append({ + 'unit_name': unit_name, + 'name_with_phone': name_with_phone, + 'input_weight': to_locale_str(int(total_input)), + 'output_weight': to_locale_str(int(total_output)), + 'remain_weight': to_locale_str(int(remain_weight)), + }) + else: + steward_data = [] + + report_date = shamsi_date(datetime.datetime.now().date(), in_value=True) + report_date_number = f"{report_date.year:04d}{report_date.month:02d}{report_date.day:02d}" + yesterday_shamsi = shamsi_date(yesterday, in_value=True) + production_date_shamsi = shamsi_date(production_date, in_value=True) + + # تقسیم مباشرین به صفحات 19 تایی + steward_pages = [] + page_size = 19 + for i in range(0, len(steward_data), page_size): + page_data = steward_data[i:i + page_size] + # اضافه کردن شماره ردیف برای هر صفحه + for idx, steward in enumerate(page_data): + steward['row_number'] = i + idx + 1 + steward_pages.append(page_data) + + # Debug: چاپ تعداد صفحات + print(f"Total stewards: {len(steward_data)}, Total pages: {len(steward_pages)}") + for idx, page in enumerate(steward_pages): + print(f"Page {idx + 1}: {len(page)} stewards") + + html_content = render_to_string('kill_house_debt_report.html', { + 'kill_houses': kill_house_data, + 'steward_pages': steward_pages, + 'report_date': report_date, + "number": report_date_number, + 'total_count': len(kill_house_data), + 'steward_count': len(steward_data), + 'yesterday': yesterday_shamsi, + 'production_date': production_date_shamsi, + }) + + html = HTML(string=html_content, base_url=request.build_absolute_uri()) + css = CSS(string=''' + @page { + margin: 3mm; + } + 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 #dc3545; + padding: 4px 5px; + text-align: center; + font-size: 12px; + background-color: transparent; + } + th { + background-color: #dc3545; + color: white; + font-weight: normal; + text-align: center; + } + .a4-container { + page-break-inside: avoid; + page-break-after: avoid; + } + div[style*="page-break-before"] { + page-break-before: always !important; + break-before: page !important; + height: 0; + margin: 0; + padding: 0; + } + ''', 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_date}.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/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 zcmeFa2Y4IDwKhDn1)b=X07&%00+0m2UY4DbNQt7TE~@up%eEv-jx1S{E%z>0xp&8j zyJP!0PVCr;;ha+ASF5ep8x-!=O;w~yMVAW=e*}V zXU?3NMHnGuga;0x{sjxWqCabNBZPGbDgHHYL9*@(eZTx2LMnI{EgJ3~9Npjd%(vlq z1svC}+p%V+n|tPRI6j6D`@h%i+2z}^?i;%i(p?Jg@7lO?(~cvlugrtvf5EYJ)AoHE zlZLC{^Cj^8Z~k!e`W<^Ov?P`z^v-V((yKOaShN0zUtga_=$C&Y-@h47=rYW82>mJq z$Dz$TcI|y&*T5IycmS@qYx}wD)}Yz85rlpX=h(eF*6iJhuVTCi{T{vp`OaChW5c_z zuDu41M-gIf+(R~VHgp`_iylOeq9@Q(=sENvdIfzMeHDEJzQc_cqUC56T8B2FZRlKd z0lER^yoYAI1Ha=pkMF8<1+Lk zK*LMWN)G;q5!sOkT1r0oUHZxI(NBJ#ev+W)MffZSs1dKT2+n8#BMPJk6qO<$;I#@3 zz}Xr!3m$7xA3UZ|KRl+(9dea=)BtTKm?aqW z;ClEx`O(7}4$hEwFkBS_3I{=&b3vZNAkh(!=_p8b5ny%+$aWb>cLkt#C7^IMV0bNH zaXlb;BOr1!;CUJ%H4`fb)w0ulv!(pzDL6?L(mNBcSoi zKvc<-VM087m#{CpyNTn>%)MN zM*+2u15%yc*fa4bcJ4DVe1A<-wOuq^^`Z6HczghUF>NVB+r`jUGSH?k!n?0S3mCZmH{nsdny3+?EgvdDEr5we z)P&lAfx1vP>O}(TL_O%I@SP=~?^@7ynre9fa54u_(hunP$rfX0VG z2lK%Kh|ZV6>*auY47lG4ueSlxF<^ZcJQ9>M6z3R_egIw{1YBc^Y=&Z+NctK$Pw2gNPxOQ@&Ziy68a1*0Y5{_8d88WU-qQ(YbQQL zNclC+2B!t`9{j-fUP7M!oBaRPi0@!_clqY7xoFKfTh8%`KNIlNFfoyZ^CLAi@GfrUuxO5smIzfgRCnn#vg2>PK=s?-{-u0(Gzn#>lf&F*j_DZZ)r$Y=1md|qF3!1V{`AF59*J#q1g zt54i=;^7k$C)bYuSN0^tI|%vUyJItcw_hPBR!{lvzxs4Or_bYSqTlU1vFOA_C$2hi z-HC@zoIJS_zWWfU`_~h{n)t=U&nCV+@ui9TC+?fL0Qo1@Pt2OA7@zpq_p$k71L^HY zPk!{?M<0Cj;m6#^%*V=)#y=|imHk)xU+I4Nw_kkOS>tr_YVIH0M|?RSWE&qzFrluf*tKYOIr#;;dYh^*ZqO+mwmxC>Lia z8&7ianfO%VgQoMRr}Lx#w|wYyzBA`Hi4P?nYdYUa^f3l}_&EACc;@+dH|}8m&ZgPF zGbQX%^dvK%Wtktcd*RH7tG0X^zbJ^p0!CGPdVNo`;ojhy&CcNF)jid~hL^xN;u5|C zSVxH#2|lb+32H{kF%bFi49oBwyrEz*gCRJ=sBcfQ!HGIrldZ;a@((9l$KhbS71h?@ zS({&mj;UsCUh}jtvZT?}@G??Oywl{oXFzY z+!15~u9+)%a9Np9ZdNMvN~};|wG#piH)}K65Y|gqP8!F_HIw7U@dQdFq^s&tnf$6{ zg;&HS<0)~AggA$GUwvOOkFTgTN4b{v7c+b z_p|e_T{ZuJr}fQyTEBnd+rgUJK(MwJB-A@`ludE3fj7|u7cB*8x!r=tP@*l-D|A|| z4l%rqF)*yk$(r>#%!_SKCX>)!Odc*z=-V?JnKpgX zH#P+>Rg}Az?dV-`&W0ySv|3K*n4kUShp&C9<2jYuv1IGP#~*+Fxd(Tvd2m%29nYR* z+PILcMP}L}ofB({wn$T?MUMIgb0#geBvmK2jA%R>xl7ab%}s&J6h8M-XwZ)JpVw)1 zAD99B{PRpevvDbi5V%wRw|l#~tM z0PjTUJM;_5|6^~Ne}n_;W7%k*vpi5UfoAjY)4QOo4sWgY?%1nV@7p{#duy%VUjrzp z`M_D{4_M{|SeDaVoqdAUUe)IS@S0}_*%+g~aLe3k@Akc#A1v^uW-B=Op3g-G;A<0$ z24-u)#Mch`FlMyZcEkS(9NWHE%c%Elnp>Sc*IPGB$->9y`;&mZWb#8-xxdCbe5sa$ zhW&zNBjj6>mcc8vYk0nAq^xeXB75V!gm>FM4OU-t{K`H@O(0cQVS#3W_8U+G^9J)3 zq(vKqO03ffCGb*@6}+BRDd8KjM$NETt5LEFmgj(X)GC(A8xyci($PBZ0P3MnA`eYk zlTHp@9fhvn6g2rWeiQHz^G5c)!R#-we-M}BMcMao`5^XXe+8|&ccKnI03#b4>JTj0 zZWkOXvssTA6{oYp+d2A4ik6Zi9)#@j>)FZm8YmhF0*Ib70GteH`(96|xhovF#^UyH zrK5h&+AV%xytcaMu{j!ybqdGqO&TH_yoh-N+QFiB!HhXh;Nc|$JcuviRzZ_z33jpd3}RRXiD#i304`Y%if|!Qq$6q^#Q37@ z|MX%lx9UU>_eGF{2e&eNncLwytA%LpI&g$}%&$QV5L41SrrzI0&%R}lBrBA+2~N(^t~fDjP-~6SNuo6#qQ!pt{+>aJ@5ES$G_kC=Hb_W`;B|o z`#T<~BAU-k{DR%i9fBxtj^M)Sw2(m&kCt~Ew4nbgHS4RhVE1G*CmWh~;ck?ciz!V( z3}T9ilqj}W(rCh|r1`W1+h2{$HyP>@X^*oqR>PqX;^-2)e5$0 zes{p=(Ar%JrODmV?$#Q$rA}@r`%c22@Rq9P-TCqzH`qol=}Wd{`v_hn7*L3A*kPx=T{wGWoAEAGAp`q`Df{LsUgd+V{GBj?@_EiW?|c=Mbt zt*YANWZ1Bt9@4R%E49p87? z&^_x`_4Y0lgcP)&y zn}F4QKEaP1COz`1ashKPNeC{FJ3aEr+wG(624Rz5q6K1D^$lQ97P|xDD|l^pu-mJv zH@8={2&J>Pbsg-kfip(o$5UrO+JuORd4|fF?s!#S*kI(1A#F zPO@rKdm`j0qYZtiQOzq27j0Oiv34!LLJtkSsd?b>H*fg;F=%J@E6`5XbOkQ^`}NO$ zJNxU~jI^B$dT8QjY!ndhL_y%PQXC2iVWf5;8&l%LC0aJ%1$3~uWD*@<;dD3xVwSL8 zf%hZ1P_N*?PN(34 z)I4KWu&mm~8q@}vuQ$Q~svw9^Ag8>|PKpef$2ZAdi{3vS4ySWb0HYycKscSwR^{UX z1|q%hL8NB`&#XkF(%2G_5Dy{`7+hkESWq0xkzuAhy2*_#X@HjtNgz!xZy+66ViMND zpBU-TXy@xg*;fYvZ$F$k&bSpSxbkAbPe-+6K#Rqz!?OYc1i0|jz$$lX5@EvYnJ&)5 zrENh|ig9OO!M$Jj!Un~Tc9P10?B>LA{2&;p?AmZCI25~0gA?EiB?Ly(bo=zz&ZJDi zj2}Ok{mr%4V$X(l{;zHDW#!q|SOKnFLC5lyl|mJ&a5_+o;X;f`Wng?B#uC6KItNU6 z<`687r;}tnPey@27kSFAluNvlLV_R|0$e)s%Frir*kFU+5H#DYJVydwc+Cp8uh~>; z8R%a37o&T_>f2Ygb(fT7--j`?>HX|$?v2}SZQHfby{4;O8%aN!oO7W4wyhgoF@1}$ zJkfh!-LH1;`eW_kk<9Znvb;6>8uMadzskH?je${E7>0>34mT69;R;lykw;-9Pf(;^ z8dRiTQtQD=X~YgrD3cC{q^@RYv?TV>!MykvgNOE~OIL=y+256#--n*M&9j6J%>49Y z>AoY4Qdc@w)O0^a{ezJr!;E$9B)a4dJJ|J-q8&$H2$`pXQb4buWQ{)>O8QY}~%)O8(m|i#Duis7$VJ@t18F zx%Rq)vxsK5u$%E0!TDKHAH)bYn_x#^KYH*^FoxyKW-f0pG}Q{NX>HA`i9Q|dMfZq(7vgs znAQ?cdZeQ|?el&EbN?eh;4V^FQ&sk5)m;^l`nT^{potl$o*-?X%Q~4JNFNro-RsgQ zbPTdEMhH6MxfWQ7P$t_M?F)o0kaOLTtkgB7B++5&R+QYUof+?4Ri1TeDM&$ z@?8_-_+ESum{gZw6Rk_k*;!dm2dPHMS9OR;CgUK|6d8W}yA&fH_ zp&q$(?ozu>X<__HCXN`t5fV?VrjD%&S0U_|x1Nk2pc90x;Ae7(=|>rPFETlfphN`{ zb<|7a9kb19051xMVn|6wb*yZZ!Msuy?1-eBEBt=kR6k1?`zmLy)hK3Prk*>0^x`eE z1|P43`5N-aKG0R2NkuAJYy-)vEuB5tCle|*jnI8^5TMxLSW%S5>>@K7L$@M^H{YUkd9d2IeZ*51*W2B8 zrzR9BDGAzoy#BVdd!WA@l3e`HDh3qlR+U5O;$5!N(qvp=tPc7Vjz(K`b!3eZY6I3C7ZC< z1w~Sj7EoiYbhKO&@59Ry1acKoc@SC{rC+r#xni&Mu{R2X?3XEZX}nuIE4=MSVpkxXMx#1n{{ z)qZugUt4dnZK$!jD?*^(BM@hwqX>h?vC(V~nXy7Tj9}Kt$}%vOrefrgoW#~S3~@yq zAhu2>ridO%lnD;-oC7<`gZ{3tKe)kQC}|z#Kl7Qf_?*%Djc{gQd;z{Un}Rc$iMwz)oM}0EAHFd= zAI{WGT#wt}OdDM5Uy3rw?$#rHb_i-XQx?dMp|xxu{v-b=oEKo6xlc&r*|UW?C|Mmb zHdIxF%{H9U1u<&EeVsTqz;RwyQOjn!*)~7RIapO2H<{*c1#=<4q6?&`fS0X#XP7r1 z9hxl%$m~LZu4EEK%4y8d;0;FEuM&VY z#Qo(2VXAD#WpvuQOD{W6_W)UZIFZqp>_A zajZ|p+QYF)Mk3gg7%3+rNi>r&g0@($D?jZb@%9YjAo!Y|qiU!iD2|E~RrZUYnY$OU z6Itl#QU2?+rwMe6AmC(Ds6mN}7?5tfg0HHqtdcrholuaYL}djVWdKL)DI%yUDuUC5 zO%hflsAy4A4wYn~Ri0KXHiDF+rxy(o55Hl09;f2@kcfz&gg?MA$|r!w1f<5-!kIe$ z^Nd4v0M2xRW84pC=JAg(8Ws6W7kp+5oJsR{aHf0W&-i>e)5q_D{PuNlrUyQ= znw~k%VAYLqrg!3>ct3c*dnP_&F2a97r@Y>rZAxkpo?g<=et3IBlc@)yJGdlc%$ z+;rwH;&oWH5f>C~L(N!;iS>oJ{Ky+huYgME7=<)H*M3)#={s@!mr1kG1#r?9pbKa` zJc^Sw;I+wwtIdj^_FI&yxm#gE3F{Xu_>6hLtgBX=>`t?5o$H)>uUd8QV0X0k7wpP) zCD{IVe0Pt!(P^x$HyKnsln_H7VDxbzzYA*KDj**i5Ut)<>QKi$CRndf0+lc(BP3|p zV3fqF9%;}8i7M!bI3%G8k$1>b#LUAa1JZ%(p+gS43tL+-nVu}#C+5N>*Ed8V@+=>= zaqc^Mb}igTx|LALyM=d;Jow+w;LcII>vP%XvRB{BeW_Q|Bz27=Rn~_mKETf_1kg?$ z%(|50R7yzK)+Q_cW^HY>++nkrRWRidWZiCVvh<8bCbUEFK>L(elNqJtFiTOGQSzc{ zBC(W3OxRBbpb9d&qzN*rG17Ou#b;5ehPJ?5B`z5-TyxCTGC$Lt=_yw$l~#Y9!&RQD zh?=@N9)YzM=LtzXXO1w4`kN|dbu=WaD=R!I6Rf=pVrw_&YhhC+ zHXLTnKGvDy%(8q9g}NAE(MX^*hYvXksn8s`Z01ne7)eG{jH)RkNE!r;`o8%{2 zPlp;(ipSja)ppa4YiiTSk2WTnAAP2wWB%Ue*ounk)>zAdWYl>54bD~yqcSzXEts^s z%l+{-Z_o@WG$x&W|C@pxGUSHp3u-#&H&iGTcdXj6|KaoF?G3H1u_eq%hbIlt%EU!z zsZ}K<28+w>SM!o27iBf98zfnV;!ufwsnCq)&K2gN*{#*F!LH`InnZQEx(qQkGmPbM z1Te(~%e*WqXTiQ)?QDHLZ!r^{V6}ucm^z|aCyF_7H~@1CfWHFS=76V0bLGOFD*_K@ zYYU~DV@KfkRP^lR%et>Nzu0WpaznE2o+BXP`(6SGuWPN+Ui;g4qBYunOSE)m8RP7U zmzwQLnAS|3Un|US2;2e^zG&$lrn#lNBf6MbFr$bW^hnl&f6ToFY*mAn!0dEwtx#tG zvf@OlG7yIXWb9^xTJt1bO*)iGYn6fuGpd!#tab`rQLi$irBbq5?XxOXL)5*L>^9zT zy%Wf)C7mNHdnur-)$g-$+`Ypcc{lU^$3JWL0-*d2kw|-Q2jwaNloJ4@fKoVMsu!~j zObt}e5vJMzRdYF}D#BA`Y(#Az@)&5k_Zf3VCX_@zyJ=V#LzAe5c{5 zN3%}?Pi1R6%4?HuD~MtWZ39nHSsc%<++96cou`yvKvvhQJOBu6#ctB`x zZSgT7Tv~;Vby%Zd>tn2aknQQQ<5FpuLI;0R=q*l3Moc;= znhArjY0{>osdMVOa>dOg?11zknU|i%%}ET;M^!xMX<2??`_gCM@GHBkj=lJ&N6y)| z+iWsw=X5T8>aNd!{Ey}SuIH~P0NO}G0(%{up%ZT&5?7OuSi zxjP*^XVh7*x^Qvds%YbeNYZTabYJ|~3!8{@m`3PC?2vCB|0eHbE<_1fKY0OohS5=B zAsU|3S!WsP?`X)R>Jm{Kk6c&}_S1FmW3sB9UA$Gx0k}U=OmtfZ66cv>C>fBnCsZRRN2x zHs*8MtrjCx70}r}k_-(&xgs24c4|mM0+YOS3q;En4azDpD3GMJ0IZP4Kb`C#C>tE# zviQr3(=dx~oUb)rdy~j>z2Hri*7CF{9|+2zXnZ1jtheUe0~W`H_!`=Oe>yI*oLZ%m z`j4Rk0MXtvH?SlgOQCawgjAs!veik^m{Nff9BVSFSS5=f9@B9wRNhiQnVS$MeiC|b zqy<2-RD(S9P!uWOB;mG#ib0eCgxfPpfsj3O!`f$ByS}#I{8vm$JJbQZaNf_2cN`7Y zp2~LKN+aY`cI`TLV{_~E`1|d?nuNoZiA`ZRD99%j_QxR(ucV%>4XVg#jj}X4(sH>; zF(|jA1EX94$FqC*t&9s|rvPO6GB_9%LMWi~ zmzV1OK7W7@l>2=C@^W9mA1LR`eSUucj?Gx*#4zeoc-_8SOQC*2V)A3mhac=^}GlF`ol+GUecj0 z8ObU)Z`q7}*R{sV{MbIW(P~!fgw(5^@{DiKKAY|E_zHMm?5P6dAJBD?M}<~#20iTJ zLjix8+kisBP?!$~g27NA5DbUH(Dh&_6oz99R{MQWm&e*lAmce1B?9=RVJ0kAI;B#c zG6G=(iDuPBCb8+TGpZmAE9TO9@x-F9V*APsFlvOpfBD@Cr>V!ZDLaeyeByW6gLsgE;(BC3`-KKO79$TUV$Bvfmhqm>RLFWFAPMOe>vewK7)IrCHCri0ty8%# z+E74lacJ-)g^h2^x1YHIuLh>Fp(CIjzogta3oq0jq$N~MMX3ouke9Q z@?e`_p@DJ{!x6wNd@>e|#rb#z_6ffYa# zgd@U0xKtC72xuZwSy5TVS5;S3RKh1^oDn`l&X_9XsmFPtQ+N`P%DCm!DdjWZ7Mbj4 z2L9uL2W@5$iqk;^2U2u`6iY$cyxZgTmU=v1 zAb2Ye3<*4GGeZ`_$va)}8JElME_Hi&j~65jpOo>Y?aX;|s?eq$%g|dONJWulS4H?$ zCdyL-!K{i16og3xn&aCkfMg-k`wPF79i)*?1bto@6=$+TKCfGMI?A1%W%Hp>B%qKH zt2Bo^RSHv&i$O~@%{2LG;v-TYG%bT>7q45l_QG}R*UiA5c;ni2>(;{`@_mX>DmP^)b$VbJejj)L9W@Nze*K+bJ&VI~-yzJA+lPqP*!@ zP8N+hrtlicO48BEDbZMQsS$}u5h+__8B2IdghmRBiF6A1YXbmj@7ne2Cb%Y!NhCm|M;YfaiE%2>FNO1Eksi>_|IJtr zMrU$HIzvL5Nn#*3_>tuHNn$+^Vh&H!GS&DAi1Q>aUo{h3eH}PI`%`$x$9j~r9+Nn$ z8vRMw2lSec^-4a~V6PeiJstwSs%n^jpCq+YIPFX+ZCbg5#6^;u6ur7g0pS@$dotal8k>4ke_h`5`g%!`36sMEBB=bB| zoD8Mx7#yG ztVMYB3~6;bA?C50=h{=Zo;j6k$yho^6Q}ZRmW=TrcoxTkQj(7;gd>A)AO9M+f~kdS zs}v%+9CDOkSe%r|CrD2KUlDgeaq9Afsm3>+Jzy z5O;J40%~s!nfSJrnsN)@*4oz2x3{#mwzaghwzsvn@GY%vZS8Q}3>y`&xIv90-sUD2 zYGYk~wj#wQsw<#U7GZBbK~B~*5vfsg6n7#zB}^$60(()1Jd*1WBRL<;PEQe%m^GY9 zs3eKT6Hy-9pPkVC=RJ9OS!Wb&!#3_4d$Q#ufAjmA#`wldKPQRLe2RdT_O-0eYrpBQ zqFf={b_~`CEvNNcmkKS^QD&L#6F~pthb)p^@xrapX}CAtA5mdQD}7$Vn+>+#!Jk0EE#*erYwSID%pwA|>2- zebdnKTSxX?xP0}qm*a~5yADNW4;geNT*vM8V|NW6dBK+*B2wACp0Rm{=6EZQwH!7! z*L0Scl)9HI`bw*GuyA*Lr%V=ynbk1AQjhKs2E>`v`cgiVs*ZWgB|1Kn&eZeusdPG% zN~P;F^ih1V`;DsSkCgU~5Mc?o zH7&n-#lBU()5!=V!aK-B7{`zCX@h$3PppS^{OXW$Mhr>MYI2Rih z`P#CZsPwo37Hfb#JW2MdwN+?Kv^2pSAh20;V||)3S`Dxn53H7|0UiS}Ht-FS7#mv} zoA{>YmX^lm=9XIEIUe{9ST9v0ioO9v-O!M3X>Muc8=K%WO-;?8hy|x&bL#PA0$^%9 zqe886Yi}jiPWUkBo5`>X*)l9k5S$Hbj=x9TiIh4x1NQs@e7qpTNIXrBMY~WRRtQ(% z{(fNq_4RbY>^QJ#Z+B;h$fzyAraZ7}dkgSrr_kBOcLC>i0`YeDb@%W+y?uS%y}f;{ zz_UE?EwFBTi_jr-@||7qnXaymzTUoWzPkrL)6>)Ysj~1?ZB0F%)ZSz`ni~puQNLV& z{r@IgW4S6n0c(#B%SRAr%HG*4##XMxQFvGde~>$d{N;yv9!~&+{Q=@JGD92&i>rz` zYN13+;`D-qd}V^BffETx11FMoNin!cLU2)#kgtM-GGCn_)w_wxnj|&fWD?9bDf0sr zXXpo}YHRATOnW)?<^9E}WrO$({e@glXW%!+ACQ^a%>Lu#tDprOp{iIlCg~#QM@YOf zE?k<6SDG8sr4X?YMwEO?3j7HVex*JIo}{6YAhrSnOoON4!Q+76sZTXFP?~IL z0GezlFu+s&Q2kl@p{d%KdMww@I-`rqQ{DUpj8wa96<<=>>)PZAKHaV!j@05YDH_>=60MOKZ49W(@%5nLg^ z(SZVlxuoO3Q+bLivTW?kDC$hY*_oM0>W9cZ8)1DUtr05aC8{}<9Exy*EJUR}lgI12 zViiI(GCwQxKD$u#jI0Aml6vEDOy#RXB(y0sG8@=)9@_ zKQM+q1d;a{*gWqM$2X$ogM^4rx=)xR`lQJrbb-Gq@G8?1Lwk`Sv^dD2RY2tBj6-Ni zdY|$LnvM-WK`cfqP|lb&nExVTrIl%%o(t0v^kJyxCTqRIvD^r{AlfR3se&w)M$l6O zCnB}~*NmU9AQd|^j-Qzt5nq%;4}&Dg`1v;2Qga^~t7A;Ch| zPRP8D0(s@$)=LMaM!&RPB2_01KOrX-rZtR+)n)Iwv~6Cw9+GtIK-F68%)T5^@CpkS zurB+LP-0(Gi`(xs4tq?Cul)02iy;de>67}ykJ#U`W>{Ue5LN-v)n%ceAyn!#Az01` z+abW-0$y4XC@ntE<%6KXlAp}a$!Lo$H6sPnQ5qsa%m@{y;sQo!H(9&|i60AOGuYoY z4b+uaCE8|RmHm6Hq(rB916%HG(sBy5aBkCP*!#dcYs4Ray|WjVk5y_f*w&0Ut+Qax zc3bv4cOmc;RMxQTst5VdMM6FHlNI!3E={@DuJii5WqcWw5qhCWsmxnO$_TyQGC0ob z!dFBWMWbYrI*=GnQEaXKj0%GM)(lGeZ-C8oiel2DJ&M|beuiKtkSl~X9FGeXC=v>K z4bd>wSvVGs@K6;L3qyJ@0;x7g??K5H9Otzen?{>OJ4^#1qGzesS`?SVGA;&zXP{!j z;HOh__ArsbOuA-|5cJ_o?&2q$8ESTlX%V46L%3RurQnVoIPQfk6Y`&z(KAL2H zf^5Q3yrp0|p8CEJvwMS(Yj2B^S7=*&ts^n)v|68k^afd@_Zl!`m|L0zi=h%^bs#|x ztgA?f{8VajyNoKAht@QCJW$i*DTNv+sNjJeJm45442ifPTDh|Hv1!)&}V?}lLc~zC}jMfiof7Lqd~Ml z(lTuB!AM{k1)B-5dX8(E1smYy*7$XZGce+yPFiFn^U-EBBxn60F^Gb$5;mm+TzIAn zwI<8o#Tig>t1D@VOzspcmnnnoz3GmsV(_B)%Wn=OI`&qjI8EyD8y|mc`<}{jzY*e> zrj7-Ved*d=Wg4YY=h)DwQ}87jYyIHDh|8cf893dN)iJMscBh6{XgY97_HR2cFkW!z z`nlZ;Ry?$LU4P7?SL=4KS=GC|r?Jc4A(Xcs-s-RnTQZ6AxskwFpUn|zSa2?E*KAlr zW4Q5uDj&uR&>YyAq7n}d3PY&Qt(}vs^ddjD&6y3iW#HMyt}tt2xjrS=-fkjHH@UPK z!cQVWn8K2(xroD;Pg>c~pj?iFIj>K}_(?@6%`}tQEak&}hcb!%yAmCH&Q6p@BWK%l zoslz|dFzqcc*{BGpP?Mf=7oIs-yR9y3WA`c94-Dk*!yBw<1g-;t|x0P{0;-FXF0Eh z(OWcU;og zzvG(ZtOH9oUhPttjhx}8MIo0KmPhc`qc;sS>lF%P8#bRmd*K%NId*F}a!XbD>`?I5 z-iGBnO1umHu#lPD>m_&J9_U#s z0RsF<8`$Q$rk|$5ak{>VJ)`3j&@%U8|DkkZ|MuqkU4>nf6nMV)Y`F{+Nq=a+ZUH5c zKk#;xB{(gx#4z0TWeNJHa0y!RJUldS z-tdBv1*81v{E?9b^XHE&T(WQxzi9E2B?}iXUNU!R?mT|p@X*j)_~gj^kp=vMQTWX0 z==?8DO% za%TTj=q&rTyngH7;Wj1(iTvzObJH*)0+bK4p9Q9y2P;z-qY0RYS+Yb}iiqNefb;+e z!*d5I^$pG&9O6N}^9JVv4i*g0=Rv&-h5-bli$@popx(u!ixw>&8l*rO90Z^Y&L5sX z!jCK%9-a@MTsTUBGCB%C8I_2%v5Qsnc_N)Rl}N=crY4E>bef;~z6=SuiLyKrY-oub z2}?e05|#tuQzGQ7MGl2ez|PEz6af$|NL7|1R|5x-ovc!@D*S&7`*CBV(1b`uLUoMR zBUFX;B~?i}znM(J{ARMC;3^HJ2{7*lMF;iu4Nym!;1fxxql8ZuWRVNX6Q=lr{PO^fv9tfLuT+WOy3mSq?&mVY?G{Ws)hS@ z{!KWD>+6LE1d2&kk~)#93gUnYmNO-46GDC*#1SRTpz-;LmdI>~zYQ`u?PHB!iU3Dtc5eS5EyY);Pt@ z7rMd%)ts?g%z6vV=~N#%#azfb{(mZ$F&4<)cA+uYL$teF=s~sBc12r-GlEqfY=rI5 zVQ&|X?eMX>)a2%FQb-7q4fzFkM4>75-H5v7eeae7lhk>gSx}9LNW_g^lr$DpF8l5s zKiIcy+E5x+pS#vI>XZs?Y91c_$b*+17e9=`IYclzr{Zl`hzqE9%82 z0XMQ-x`$1-x53>g*a1IVlI|d3w6rBSN$QB~4`Gv(&dqIlAeyx#Jkw0E^jS&|@ zEm)1|b}o_>zqaAQ-IqRoR&reE7<1Hryo~#~OrD{NGnMAzb4S$U%UEkpsL~9|9;Os_ z(T~7>Eq-yO6Kt^L*J<4tHokELS*}FKY8+Y(gw*-WGF@ygiBH0uB()j#?u6{J%+?&I zz>3@R-rc`G(l8e7+mlJ(SgL@1(+%74`tM5kdH#>}4F|9JDIR@oQLElLclWWIL!rwR z_+SntRv4XAZhIg46M!8twnMgz?ub`rH>=};vJxHak>p`HXOwjY{Ip=OlI5K`Esr_C zhpbvqEESyW-xRab71`*HmM0T?D$+?w`{G_cqVl=-H(Yw`(r*^;E!FbdpyFJYD=P{+ zym-&3b~n``beh@*um}4AWsg2|ozN*(mh}(<>FovzDJUE3fx<8z3dFj5po~mTE*&ff z54k;eUJxXzdCd`)EUq!lo~>S zwMmfz3n~o@>Ip@1bh6P&a;%${93^-bmrov=l2e$bc!g&7iV3L*VG{726=_nD%|x7{ z&|pU59=OGDl6wha;Wo4mcJXR&7dlWZ7|=DwfyIk6Xt5} zA^ghiW&+^^^gGvesplHhF1N{cF#_WiWPX?=G{tC>Y}cQ=NgTPgMkO|Tfi@w5DW+sZ z(C{?);*;5rAIpC3`nJn5YF=R*yR9*XF|Q3QFX4EVC8TC}L(CG?E!;Bi;5n;XdzQ}X z=(;xh!v%}ZyZQTg#ZTwf8H4+*3SLtcX&8A23;$eEg1rL^?HrSRRJdyJy5V(o!->?> z?UmtwsU3bYUvm#a{9PcOCb)y|Ubt^fU!TyAGVxHbL}-F1zf%kI&(IfaZ-%=famggx z-qq9y8BE^Ild!8GW`K-UF6PRMD<`pB)?17Ept|43{89vDgPYR7tkc2V5$Owlx-8k7kisr}96kF^Ezk4Km zRd(WN8!R+BV^F<2uj!b}(mMPd+;SQ?k@yU8izHk749x#iTdVea+>N#H=z^UlVZZgV z@-nQi!<8%-je^P5)~GnxS*pn1EF|w)6i@}DAVm=yq<}gz0Tlrfw+MjrSoZ1DOX^ez z#g3I)TBes(0eIK~Zt6t03ca|iOXx?$#uV+_Kwz!-U+ZSQRF;9=2F zXFFM1Bxj9(gMp`)?j))ux1}h;B>x^Q(-`rSQ!^2G{4D5MlsK6a|2h|7{s%_iq%x0G zUS?7upEVOPt17X=gEdK(ak6?nlPe<>*J;v}9Y|%0uR3*aYD^;^vK&|}%p+?sNv5G- zOK!S0m@~=N1+ym)WPktK{_Ak$p0Ra1KGSDZYg~z)^+QWX=e8$*K-T&${ z>!TV~cJR{0>t4dP$9wj#-@0>GsYajAc7af)Agcm>m(XA<7C&o$2UCeBi*bbRb@>(i+vay_dCY z^jZus(x7(4JqmWzOxNO*^)Z=7VoI=P3yi5?g;v2jEV-FA%gihv8%{$@1&psKvTWuP znjV=oI6L#B>j}=>2KoP_@e7gJ*EoT*!5x7b(Y1nro0^1XRBvd=q-(3gsL?@&YVOJP_;grHaXpRbM6gTXaHA$U)|-g4 zlr|cHyb~iDumcR3{7Q8^6fsd^%+ij*O0Z)hII!h^J#7ljuJ}6am;bA$_PR=x%&eBk zxwn1mGdI1JT;?%Umsc>l@<7Y__XI=g;Gep(%Rm_TVQVbzz3O&q;H9a!F@f>im2dp` z$#{$3SgX<+w6;b^3^P~MHtR!2ScfP-5_>RT<(AWY3EBUF&OPx zbv6ZYdO#O<-0{MZ-fgp-K^xpDxB2304i0l3>-D)cNS^@<-~ zSP@Si(|DX6E%l3E*;@g3A=bfdpD_-_>SCQkI8X*RfaaL@iIBwoe?Ne%5~*9f0&;A$ z_B`O=p+eK`vXsEmtb*dif)Yeuxt7(iD5O?Vp2=bDNzLYRYBSr`ah)HpGWpe#vo?rqL+%h(1;X2!Mia3Icn=!jPZN?B#Mt zG*BRS^?-5Knu<;1_hqXY+;1q+VAiU7e%WhGtQBrIs#rht9LBY+D;IVQtQ~D#$Kd@b zEitTZj?0C6u;SnryG1jnJa}o9eW$6+Wi;KgdF_SUE}GxAe)TZ8qcx(mj!*oa|B#EJ zD$3%w34P)!$Ht6-ZEC2BdrfG17KeMARO6@(YpW_*154hI02vmZnA+@(K;_`b7T_-5HN63Gz|hIHdjvvOCQePb*&J7G5g+| zYwzyU8#I{rGEa=Ye&6Ccn0CQEvqo3cMn@8Rn!Y<4jc&lqjr;nD5Qp3)9g(*C4sEoV z)P~{8%PVbqmA!4l()HUhUO9W??rzr$v2ClPLoId8m#HKvGid;KE~t}^QryL2LL7zl zkx;2pQBcZSP_U{4-1)FMz#0iRd0Bh3ke&$eq;%3WxFbV2#m4mj3PegLuHpYDbm;w(43}E)WLRENrc8#CU(bk&JJ)r4KY5I<`$~D6^Pu z*|hG$ZTm*r*4I}|B8tl4JAf!3wZCJ4DAE4vYG7T6R)eOuKtFcHu&IjWedRh<%c3xA zOKITd<>2XZ>096-A`g;9qL7*nP?K@0ridlxU7g6CDG9VTS;^@!TugR?DNss1iOK>(cOJIU^gFl(}x*5)PjP~72L@<=toYd{k~t#{&bxEY#a+BwK&fnuTt7er zW!TF8ZdEvR3eIV!l*aZ_`9qPNaAwet#0VNRAXm?T80ryM1mz^tt0xkb?IM&S^BIyo zz^+#LdUalN)FV7}bx|cf7Xu|JF#q}^wXMt7cGc;x{c~Maa}0u=VCmdWUb`T-y`tyw z<|BPA#k3VJ3!7{=Z`inh@A3<9V|zWujj>u&31+tBwI#9crN~aBof!I}Fea_t3TVlG z+YT5C7DPJ*>$nO+pMphQh%tDvp`0xtBgj(L5(^cMBB^pj7BZgV)~3F;o*u!FN$S@u<79j>brQYcv&;Ym@M+o@BlW+*G0zLE@rZ4ZXs zhc&F4+>XgyTdh)3famUh01PhSyC{!OE5X9-iwf1r!CfbUTUOK|8@5k|283xGKR=z-%|9t#gXk8z}Ltxaw7pxxGgpZ11(|S3+K1?CpEpgAhgTfV~vxYGxx}pR5d*n^ARA zQ5la{+Oe)a!yGfkxbQ|{s^3vQ;_;R~p#m=Fk2k$6XvK{(U^ z*2TlBSdxEIyf?OHOXEtmc}@2B*>Ra5PW)*8s-@`*mR3N7jdjn5-_5Rm`Q-BE>iHSG zz3J*pyUr~Th1<7uXos+URDH0yWaZj=&jp>wAJ4vYp}$nj=Ro=2{V=yr?$H<|ci(W> z-Efl!n0{3o4OID)O9Q9?p!Y=gvM%e3-BLpVS*e`v{Xsfs2>p~Rn@#am*;juubbI|K ztvcMDeWrKdwyvwbXSUX6^hPu2*G=@hp)YY;@1=WIEqnNw-n;UWFL{hYw;|NlW7DtP z3fdw3z+S~YfP(a1S#;eWAM`lQgcM3W3fP9+84OShcb;n9(r{7#rv9Y<&B^RkE>KmW zklb=Zla^~HU4m82ImH2Zsp2qI9DCJ@b(>RbHQ9S_d=N9snszL!RR34@TmHXi4?T;S z@#};r6g|!mU$`nEf_1-q3dC- zFUcWr@tA{Ssv|DA`6q)EDisI-?rw;IBI&)u$bmwo;A(3*FSZ2ytP#OI{4CPwFsHp7 zcIEUnrT;{~l54gUNhV+=-#~663j5&GhzZ8*@>_@$vF(szOX>KvZsuA(_=oIsf3_K7 zm1~wgHO0E`?7HsjCR~ zGrIYUBze8hy#w+}qvJvk&SZpoE^bvb>FRjc52XmGvbvbODytQ+7h)W^4pLT}#CODv zN|Xmv%f%*oD(GIIQ62!4p{FfHi=(VZf=7A%4a_%J76$^>KX@#{*Ne+_Qj z*uR#$V(n`Mk~@Jfe{5iN%)~s!Mjy+b`FFMco4)Hhuj=5B9@!KU#C#0vp?LG7t6>FgARq)eC&0}EH!eI4-h4jJVy0k|7sLWt z!j_SuZJn9COei3iS0E>^oG3^*NJ9@flZ04Y04;r_V&#Ho8mjP);$Ye`IuFz6;s!a3CpaETR`^Z|ZKJ;m^o=NMA@$ss6hB8l>x)0j+2olXvNXR0g0 zJCnF!Cb?${Oqh?TB>pjb1Hij*N8%+pNlvFy&T-?F%7bSyoIjO;ItT`z*c z_znTXcR#-&+(|uUwuGC22#|1$^I#0Wwi3;`Osy?swehQJk(W zr7Ph~Y`_vnOgZgL#D~LVUJ3eCWDz()v6vTvS8}gcQgm)<%ED4{hAG#(C<`?+b~gs! z&i$@!U5qcSKX%DO53Svq@813^Uu2D1Gvrh){H=c6wCnM!2RizO<=v}>EZRo=+;^8Y zX0Ohg_Denx&*7eib>PH{ll>4Fo+JC4GDfV_m#|u!PCJRooF5?Cl6i3*I(3hPoVFyp ztBW#{da$5n8B4r`$Mvn}%;~v}HqTCvIJDTXEh9wlx8}t4S*;i z#|qh0Df+jQ&?p!HsMN8wu}XLP+v$zf{*;#Iu{FrW{qA^!zP4%Bk{@p@?V8=O#Cl2A z*Ec(A%RYZc&pJD{;3RGfH6<+GdVj~jf_D$YZk=7>R@$q#I6rcoVi6+mT27g#b!s{tls5|I(-W|y2e^6`zn%+ zO+&uVCd(#Pb*?+oYmOdUlGwduW$#0cU9)!whiKcs#Xg0fg%NQStpZD;8C*3R@VH?u zLIe_%tkqpg7a~~sBKyG+Q=-YVyeg%B=!($wsS6Oqj!>mRfhpjbs*ru^|Fm}{;Bi&g z`JDIO%)Hqb?Y1mSwzb%n)Md ziU$|YxoF|Sy3Gq`%;_K8G_kqWV5!5M`gg3G{uKK8qskkg`1v)Or$=Tr)fG2I)l|J` z6jSx!Qd!L#!xE=BpTb5t`zlR4YG=ybY>AX#@32qWx{jaMZ1s)j2w1x4VLzmjrW>Y( zRy^Hc(}Gan7MFU9u88oT*^OT*17!i5zT+N~eam z-7AgQVE#u~m7PD(ACztW=-i!Fir_fIKt(CeDI;kar58}pUtk^n__``r@fif=a{4Q_ zbcv`oZQp$A9qF2m#5z}XjW4Z|cyEoG&~=2L*3y!8AiSx5vCzw4*mt_in*uL4d5 ztOo~?QtnH}NAfc0!RNu8Ck9p@-Szj-`;AfMf8l1-zm=CkxD^yHg9RS83cS>O6#oh7 zgw7VBAI`_1`n>Q#AA^!m88-+FV9;CTS)P9c`&0+pI$6*D%6gN}`jIa$^dm1ODP4_} zYF1kP#`8v1`{6vtpWQ3`x!k@3hw|$V9OBnq*4|V#$A-ypTdDoHml#!)bL3tzz87}^ zg$kq;o>F}goT9=R6Q3$SB+2`9X#@vv2wXQ>=~!` zN)>xEIa2_j(yn{tYUPWNuFabx>z`~~6S%UcduZFh@ro6Wp^B2~7bi@D1`Z_%@G5<1N%! zSrrLm^aC8+PBCZ(2c1^2WmZ>vJ*Hh}6&Isdi!eW(wD!uS=x~;Vq)v@$AKvZ1J`e@gMJ>NZkD79#L|3$}_*DiSJ`qu_7inp(N zEV_8~x1|%BTDyAgZJaipo%1eQyK3iyk=YxryJ<%4;L1%8z8o9uop^L%?AtBVTV^&z zmreK7)I#&%r6Oo{826ypu8DTXqezwbEUIjrT3O*jce8 zMMbvXr`iSiYp{p})DkRu5gTMM*|J*dAKzJ#N<^t}*P|N`jcBQxm4qBsT&7C=Zq7=e z)$B+N_HTc<`^Bs7_kHPe7cFdT>ggE$&(OgO&AzoybdDaJ*<3kcYW?@PqW+RAHrx^4 zd+5an55My4XAbv{{@NNoS~qdRo$K!GuG==UZuqdsA~2dS*9I zj`(_Fjnk%7Pp;G%Flsg+4>lC$!MujH#;M?DjpcaLg3g>JP1JJE?5bWqdY&oMHfOzn z4@}PY0$x)afoqmCMuU}h2Q<_#Wk~TIdu0Y`8(4v`@iP0)v?~{X>)uNcU(5Fd%^N` zPrUdDh8l)^#rIsjGPS;b_SU*tk)q1}>z{sEdVNm4>nNvBqTMU)J2hjwsJXtxK@}XR zVSAG4Yi{z1vSijhk_Daevsc!J1jd_~T>}?3CB>G2lg@9L$&vZ(8%z^BgXl;TdW;vhW68wCI(da>lTL zvRzl*IyV}cl$sQt=&GF4ob0MyAf?CXZTx1|yKUCXV_A{7wJq?gT?&`B4!E{0DHXre z`A)Xc^cIJ#rKM%KDOKSJ#zi@B;43-J=XR#Y2=e*B>d$9tVWl(ENA~h~)#lC0vth2L zeCo2yS7C)e&o}MM@ip4ZV?{~E%VU9K?gFQ@aNwKs(hUc`;>{P%AK|e!&-HBCIP=1E zar?jH=kd<~U3^|<>e{12Ia!<-`wR2?j=AU!XrYCe3s?{Bi4Pj_Ii1nQx|&I4r4DOB zPjl_misG=_n8Dtd**`DLJ-IQ1nJ;?E3QFTRyQLGchZf~q#6_xK9s|l}N`=pr&hcpM zbsF`qbaz%66(L8U;$*7fTvDrG)D2Osz+TsAaY;(vl4A2)mdlFNPHkG*SX^HF%v&?Q zI{ZiPSKMCibh&DH-|O>3fzZg*zu{@|wdJK3kN(NBYa{a`-ez~Wv?7AJlvl(idfn!4 zJ*CFupZ)gL%LkicbKMPr`&RB@^nK%?e1v1aGqhk zn)Gy)hoc?gpl#Wxk(?MiVm%8fMri@%ia`vw@pT zZi>z_sm)BJ)F>g+46{?*0hKA~YX2_8^fr2=(OApr7 z;{k9kwNbRG&m>Ok*};D{A2@N}+cORfF1q9D)`N?m492GQV!>L|=`25a?UD9*&8?=R zcqHWFqkSje98aFi!?lY?ANW*_#V&i!)M@?Kz46e7+uIta^;S$-UmAYt;n#k5@xB{( zyzs5H>rVdW3)bBQ!bC}4Av)=-RXRBgc{cH~W%1?4(BgsitWqvaz=2ddMxtdkGiA!+ zgzXv4RMt4Fi~1lZOF2)=vz?aZ>*unMsGsL9z|TujKOMUNDtnH>hd{7f1XPH z=-Fg{p341|vk4x$K78sw&F|y;lGxuBbR}AHD_6!>8N-VQqK#sH@!@Q_*7ZD9?=@3( z?Oc&jbv05{Yj}2_C+n=HSJ29QX|Mcfntt|*KYALaJ#=1H`K{2Q2P&ZJbK3hSyPdA$ zX|qZvOm3Soy}HKhv@ABxTir*es48uBXMOG5WW302yZli1x{6Y_$!G)`G7OwNo+z3+oxIL@Z-X>FhI`>5@wriYH)Ro^Jm*Uhn-*0Ktb zzOppur|qZyws&$%b46Ka9pnx(W4nC5K(WYO%nal{ES5c^?WkGHm@z{uy2Hv-@VanL zyYng-S*1=3v|_w*W9MD9I4@m2Z(T%dVo1IhsczVkk1e~YyM4U$Q^TdcMe;zQDHgzyPnWIeSXbi$^wP^_XN2o> zJ-dHB! zYkO*F@7?_P=Fyu+fBjC$l-QIhB|*uX%ZWBx}=ZpJcrJX1x)81v!BR1<) z=5q?xLCKe_PfJ$I5`}&#r{=Y`%tLqle0*F?&1-3ypAsHlGk0P@-U$lO?0Ara!FY&l zCzH3(8ARSkn_xbdpyq-q9#R40N93bF)-HEjW^Jp}#KcifzZ;aB$r1jrPcE0>WNnz3 zSd-l#TvJXktPYz2-`|)IGt{g)>en$Lj-`y1&mIS zgJlT;YZ@P7g!d&GgeO8*e+WS1^LnuYfN6+`^6&{tjZatzK9Q2(v(BD=cm&KeDv@>} zA>IXB4xa~@6nUL456ERBGlCpwg$PNSA$LL!mP1I=(~>lnUkhmi5=mz8Apnif=PSgg z`9n8QI%3=#gl#!BKG6Z-Q`#z5#@i$m zZ96dx9PHEhBow5fIm!zMF$YH{$<>ZT@gbJS{ z4<91`A@SLQ&+RcRw+B*Blk2oChcAN*j+Sg88;waJF|I;x!G|>Tc;Pw&W8*|K95BZC z&EZpNtPvsrt!M#%AwC@gD2Pk&xm+SbNhv`lDToo^XW1nEAWYGtaq&T{`F{=<;;7Qk z=Las3-)}2&!$XKrCLg+yW;XQF>w_C7kPUn?lR`8^RLlv|GSK0>AyO63V8AA17#Fgw z(-Z@h-3;ia;B&g%7G9xKA#^WeL%ovI&Itn9|=K{!Q)1fy7iwYgD(^md?pH4!6ybvHYkXV z?|v}ZBEs{*r);+56DYgo^_h^kNL_wSq(I>x=2R#f;&29nzy=Bi-5w#2*S3XR$b&)> zilm`G;B*Oz#tT0D3O-RYm*mS#_y|C!UpVAW<8uo>7+={6@L}|MF8wh5`YfC18q&|Q zyht^}^7&1N4=Xul$n9}MadMQy7sPr#LZLKyeYRT&c@Sx(@WH-X&U}0>H{gJe;KNW& zmsir*qyM}Rr;2AJtnfhv+%BxUm&PX;(HRAm7Oe7M+Ll^p$EQkUu?KLt31I;rw8_d6 zuoe7?E@^uZ3IiJ`9QJsHd_K2FD1*=ES9S&I?6QTBJQm)SUnH=Y3#ZE`jtSG@`;g!Y zUs1$EFbJaJ3Lk`v%?4%hx#dAfNy-Z3WcAt^c4E(!z4Q45pC3K<{(wkblgI0U;^Zg~ zU&P}Lfx;25BA*}lKp8vZ4`{m*47qF}!DoAb4}5@6vJvbq@Oky04`Nku#L#TP2NlT2 zCm02v$Ak1Mz=u(5XW2A98~H@=IRZfw61TDhYz2Qx|BwfrcDTsn6N(gh75M`muTU0W z5c=nHxI$r<8)U28>;W9XhxbudVibvmvP1v*eF2THq}ZFr=f(FRF$}UHgJax{3t1Lv z=@CF;OC|lzjt|yQ$|TEy!S`8wVm&lQug{B&kt4|~+MY*>feTbr?DGo+fKABlML7Wq z03USJ6^__$Aun>a?ZqwdK?stK+yT*HpZ*K@gBo9HiQt1HBd6e#%0XtcfY0mA$A=0p zE}kX%NLhQSR|Nvd%#L8las@+<94a604-l7Z55f^DDwUT)z;?2;?=}4gp^v=(LN9-5w#aSitRt z8lsH1RW=HV4hQsKC>Tx`WayGdPXn!Zc;(aUgFXLBq>2N2b;Eswl5Y52J=XMJ|K$3* z{R~d!3xK?#-f_%5HJ8Zs%vjUOue-jUzOHVn-4CH5H^~wIOPVgEN6Z^2X~gMK&@rrZ zb<7x}PW}viTKz7jV|<)unr~oX|2MeEe1on6wS#towwMQK34RAbi$G5@o|pHGo9Mfs zJI(L#Wb-@pkhy|VpjO;lV7@>*s1}jP(pVG!6I~D5fpKst&|}PmuD`+O@;q-AMevg7?fNlj{3mO0&0PO&62h9S_2X%uk0Br(Qg68StvC;H#D}FBm z#Xu<`;~+hTHQuf=*3wn{4BdipuJ;-b&@ze= zo$u2z*S)|H29HO_-aGx=bqVf2gZo$G{-2J$clx=bg&uR{}RHu9nb%B?%cV8jyb=9^HX^D3dC=9-uWgx51q5# zg`DR@_TR%ZZFIzP(GlYz96yNr>u~=!xpc^+pK&u}GX!eDa}&WkeV$FvZ|HO}e=v5! zIy`p5`~g+SdO`Rd#_wR}H}kv$GUQLva_J?Memner0>7fCvfWTf487$aqnBeJvM{ox zwFf0CGP>hqpr67zBdxjx`gAi`{8W8SPfM3P$h$j3C z(Zt1|Um?qUn`jc^ISG8K4uk%KX!5H>)yQwvD?o@(^+C`f&|{!4f!+k+z3N{OO#zRo zTR`A9Z5s^0J)lQH&w<_m{T1jZAjG2%*XqHm0dkn$i|ma!%sfieh&VMtKFx?%bSF{E zw}@K5Nz?`&vH2kUw!co)fp~QuAes#vT`wT(Hxu<-f$Wcay+4O(sUzwGC89+Ah-M!slTs5Z*%EThvN4h<6qj!z}!YXeqD_1H-a%qU8v0IpVqEeWFznqSe5@2JyZ4 zIigFJ5v`p-v<@b0y$5uZXajI;1dmO4b~EhHmcJv~hHx%j1rvp^#8h2|=P$R2b|F4j zfcKRMXAk1D7ku|29{c}_=xXpeaDeC<@HzM{(RBf$>%r@Wg+w>v*_#p8Es*c6zaqNr z1kvrU65Vkd(VZPcckLv)8_(SHO`?18?xEiieQbc}=j+QaQafVg{Vv;FTU8ko0Dt-+fE^*n}U9N7Ba@o{^G9HV4)v_;YA@SG8I{x}t$6p`o`0HaGe|@auua9;7^|6Y7!{+JLtQ1o~T~D@!-Z?J9gobYFdoT z2i2_|v}lCwi}U?=r<$!EjVfdB@l%jh{P5gw`gaLAX<)3iijfQyJi3#f&j%ks!YxsZTbXRZ)#;b% z6=>GW^g4Zwo$O*89<)5{Wgq)Fz(Edim?M}`Tg)X~%4J;66+D3_awVqyRPki4<{F;D zQ+XQKavj%m15f7}Jd+!_iQyZHquj!++{Q6(=ML`V+1$l*xSMhj^Hm@p4|lD|r>K<~4jVU&3p79k1sNypcEYX5PYE zc^hBK+j$4?UOvS4@yGb%d_RAJ5Ay^3Ab*k{;v;;NALd8+80K<+iXY=o^W*#k ze}?~npXAT-Q+%AC=Fjox`5AtezrfG&7x_#4JiV1kLC?Xhdv@>Iy>s`DUA7#`fp=u< zwtf3{@7Zzb_I+Np-?v*XIrc|8qW!XONvM5F_OYnit1B^eH#VTIB-LI$)2^OrZ;>nQ zt&aW4*{!&OJ+5G{ue7P-nA*3ieTUk2s{L%W?^63dwFgJM3y#=>W2(OcVPdbsY{B!X z{&vIxR}emqRZN6qw4=4vJAd! zzI}>spXRH>1m9>!n?lj2__ir5eF`Jy1|YPA;w!ODB}5u{UWK2~clEL21%Ht8yyBHm zyb_96o04rpVN58D3C&ACsbZK=@#$B*+SI%KD*S#Ge!mW1;*jiDZ}sbEboh`kuB-6- zRrvine0@cQ->_zNL>G`ErzklLD82)VZ&LGBa!4vJNfl;N^Hm&^daw8JW)sqj-OCMm@?rNU3Ca8fGdlzKO%-%??wRG2Y+9dS+#q)-!#Pc1Gk zDvCtH;ZP_T3bB=su%WE(9{k@;xAFp90>qyp_`99BlpEA$P zAdC>Q!vlxV#5wc2qQ6V~5yEDKgwJQpi6tJt_v5<}(!;xG{><)ab0=-T_!4-%6ka#3 z-nw#!pZmeZ@cJ5r*#B6)Z%^RX@88*ukoiJ*zh~W!^;<8fe|84Eei2@~*Kavz-A6y_ zTLG_shtSC{H>}xu;G}iVYY4sd4nkJ_hP5l#{IcL3_`VO`htD@|fD4xIvTG3fFb`gr zZrHl#fWNir3wYfM_uI2&`|6cwYWQ=6{`ergKCpG=fgN}Y{t}^2%Hi{YZ7a8~tqm=B z6kbn4h`D^n_T78-hvvZRzrpsgN{n!7in0<;hR)wac8E6)o18rQC1EGWHFgl7Z7z3%F0#+{oT5q9O z(J#;&=$D`k2KaV8{96c;GonV2uNgT}9x6tq@F@m*^b2^L37=-5UvI(VV)Sd!hR2|l z9Q=hHc~K#>lzj4a`pGxxC*P)@B--;Re3k>Pk?%7ft{6c_1Y`v*DnJ3y*J{vR2F1~2 zc&tMc;ISS}gvSOn1s;=VDm*6Oo_hK>zlB$E^e#NsquOd<*pTJD?-q z1+BdYH0ArCyZ3>)z3lOUj>Q%0_61u=+|4IX}<(5V?gfH;6Db?SqwNWfPOR3+kNmz`outw4#VS7 z_>X}eeGMK@K>HbJ?d|Y*C;W$LOBvcOhPIM{HvI(N{VBA7f&0G#kMiAQi4bW8kOj4X zPNY#2Y6Ax9LfxnriKr9xpx?lET0q`)AngV!9?Q$b56f_A(+4w)0}{{Lk@n#>D9 z;xj=8vtR@enJo1a#zq{;YsONq_X@ar)v^J!oG* zI&FCS)YAwV-sU>tvPj;8ANbxQLv71>~QuHG#k&{GjMWOf3&}% z*9*XQp6RC$6`kqr5$_diu7J0JN;I#B{~8#6Vc6?n<~7H>4Zkl2gn8ipAd0|fZv%bn z2ZlKax7{M5Hkoj$z`zWXSM`=i142j3g~-Qd%MPYvENc>CaP6dYVLIC-#gVDQVp zm(DM3q_AF+5^|KSD2!;<|g*?So7>%V3U|2iZt(c;$w?@P-vVHNYZAATBt2~VM{BIrK0yA*vDN{2G0=+Y;&}3g$DyJ6$s1Na zD9&D(cBCFh`oU+?i|QRgMb6;*g!d(k@e+aS6`TPK~0k?FEUR+ox z7J&=J810NVpL1DU2pg4q#_R()HV_*?waTrGs8D;WLUJqY)(JWxEU;zChQ|7Ymvsx_ zkn%foeoL9ZqjKV=hT|)jTxvVKbm`$k{r!h{=c>`l8wPWew!%O=Q z9|lA=4mNZD5Xz8=wr{mqPTOaBA7PH+rAPbwj~wY= zc7(SrJ9LP=`S=%Z;nOc&(ER@Xqaa$0o{-wvO8!gW!e-Hq{eH2KaWZ)TFsC9Li$M#A znq@?OEv$YDtJmWWhoWWCGDkzIF$Kta2+)kf?qe(PvieTn(Mh2S1DA2_K zr=cc+x2XrmBSfW@Ccz0;lGUBeroQlX^MbATcOohNW48|o88 z7j8^%wr-Q16_9SC+JjGv~LrF2ITARL$0QzQAnxVs>m` zo={>i{d-|;e^X=aHsRC59dl0H{#qe!xu$#e7OUIs*eCt>(giiG%}Xmbf3D|?*jHBe zus(zBqh&SATM~b`_VxUNzi+u}VD<@?Jz(>A^qZ%rS{BX~+o#VQxVmQRdlpjx-#@)N zonp3`jYZtTdDYELi>ua4OE&g(T)xZX_6&SqbJoiuY% zU}LKOFRLz?J#EvGyS}z(OMA)o^AGhvS_m+~pYpqydw_k~L>8s%no zA6vfsf(w=}KlTxQI(n3}eZycgdn@oIi)M(0a@!d&F9`FPVOhk`2b>w?z>hcwFETlL zW58j|-a2sTVdkh%MmP@cwhg_`mavDRM}$RakBpFQU@_)0I1!lCK5;qp!hnS+E=%D? zANI1m^ec}?dfny0bxsGaEnqCtJ05sp^Wb`?Lwb|A*y!QGea!Vj3HZuM(Si#KL_bi5 zo5OYubE$WLs&~?4#Hf__3p^LnAPYg@|32FW1&@RJ>llwnlxj7 z@^0zp6-BpV(*?i3XYq;&F88x9?!5R73DS5Nr3Ux2zZP1-7bW^qRwhPKah_A)P^l3+ zHEjYMYE{eWL}l7`l_~8KbX04hbxf2Y7F4Es!d^1d)+g9sPhNVmAX44a>#nvpKHQR; z*ko~e-A!%1TQ{YAQGawkf6a&2JQ2M4x3B*2?MLvXbFm9s78=dluRP!nudRxU{v{%5 z^`gPO+=l{*wkL~uIF%C9C|MB}3iQaxI5{p>V#Nh&jTopEJSFn=PJbS4C^>jLlA`+q-(-tPo$~ ztg3Vh1^)J)uu$qNo5f%Ems=i4N2`Bz-eV`Ff%{9IdwtF0R{$qkym$Vttor%1enq<3 zxv06tx~v8II&W}4_bs6x;>lSsDnwE2MD10d@CtO|0%~3&bO?a_;`)CvMjrT(W|S`NYh-zqMxP ze6wlC)q4v9H2uqY&&dfW#JV4M^P!annq(2v<~ymB??i z7BOZYgF>7T<+u_~@8Gam1tT^<;UIn#fkP3$8C7VZsL((m8)iF>I%)TvEb$H);wu0i zB^WfBTQgzNy;nCcINU#X2d?XUp{VTQTQ^+t#~ZI%^vaQjWqIZHfWK=u-u%>whtJ*L zxAAFQ!t}P_2k(F7pVCR`%Y}dZeY@1N@A7-97uAAn`vrBx(wUx^=HDJ79M? z@{g^W8{Cg$4wJ_`lS>#I`{qgSN#}`o&7SLg2S0~r+~~t68UlC!{nbbCr?}D4A;EMD zM)L>Pao+{|qiM6%=tPBF784G&*_pG=#4V%T%wX~xLwV2%GLW0@baCH3V0Sw5kFK5{ z*e|_lH+#)9<2~u0kWSRa{JQx1S8#iYbZ&j%?*I73!;(XK#omFx?KL(|TL4z;gmGD)WP) zMwVQJF2i2xNXm|-vp(Q(Gd?ej0Srt)i2w-w8#cGTz+Ni->DHr{tvc^9To=O3#xkRH zh4bR_=83^=mALb*A5HRn3*Z0KE02Evm)I;V?3Dhe=ilc9Ow4_fex59j5H`H<#koC3r}9?oX4Y5WX3jAaEvB>!zwz7VA@9_>oecm5%h!|^~`MPe06ua=OrEOhOf(sKEVDf2#tg$(X(6woDxtVbNkZw#M)E|* zrU&Fm%$mo|bHwe2-&yg7mFo*!le$;`-R@tz;)Z2y-IikMLx_JJA4<>o*KNM8ZO=Ua z%C2@(S;Kc@QxCOYziC~5xwS=HQrmlb;{6?a{#tizcJkpQVU_EoXP8H``&C?IGTIoy z#V|}6kPhav zby;DF68AhW=Y-(#c{L6i{`-(4s0@r;QA|WIfM z$6fR0?gHtMpLe-G!raU`Vm&sQL^Hx9DL^U`u)wk$K(B{s4KfR2Gy=y0)q)c1bs)eY z>(fd*K+O-q+zL54^;yO`<75iRq@^Gep&*wonhHZIp+1^=cSXK)8 z64L`s&Ld53uWc+Tl>Rg8C3jfc=GxARNP74M(1IRx6u-ndz#frIh9HPK>L+2uvqSP% z`7pzVf>!tf6+Y|o7%+b66~BN<4Ub6g;m&anJj8Ir?g29)Bkp0q zNf(>MFG>6V{2nt!N=?Ow@WJUsmmdTlZ#UR7FKU5akQ^d%*$|_%fF;$**wakg(0J12 zNFvf)o8sOmgGvX{JhS`Y$_<@r7IAUOhE&6!A&WS5^O3tQ-Al5F2M_ji5KW-jKK`H3 ziVz)BG=5`UHXmY&bOElwQlM##;*D!)MVB)$Qq`A6LNvb#P0IGo53bxOYMPg>&p7EF zt1g&D+9_u{4<7997-&}Ab<$qM#$iSv0#z9OVgx4=Vm3nyN@uVP5h)t_(YN+g< zb={ghOO9+mlnA(|ukP8qXYIVbUw%wKM)RbDA3;Xch+hE9+b%k@bG(^wgv_x~MH~tQ zMkaa5tQv3p@?AcP@kt_glhA^1(UT0U4qYU6C{Yi@8liiQtzQYG3Td)ObZS#0rC2^{Y-mK*FH#dFyP zSFa_w*yo)$uRd1WARI}!W*EFqr`KFi)V|!|_PI)@7L_j1m#n$$!bXOvtKxW&gZb2c zeCxof|10HiYeo(Ot5i8)WCJfAB+m0FJLTt#1vVegda%xcZ7$Yig6U?(PN~zr8g^n) zzE;cf$*`71oI{|W9d0pQm+m$PmgRZp&ZQ#UFX9C%}cp(Xm_wO_v=$uO~6QWyh1 z*y(zF)xf6zQz%?TP&j@1CD434Cm(nM_u6UeS1ct_fQ^xEfT~J1|6-^$Fz(GWz(TORD|VGdJ2+dh_FsHLNeB!@Ta> z(l1NaU7qZ;b(L4#UsCFyP%f+lJ#G{x;!V1zAVSEac^x7ti#yQEB(z2G0nX9Xk z+k>qWTA=dA#vQ}A^N$0=K_!+n5w4VTNAc4_H(Y6eD^uZ06L%TjDu4qCHJhx|16Kt2 zs~aFup+oV(Q{=A(|HWN^?-P3AN*!F81Xm>PT>KFKDO_oU?;%$n99WM#rCZ@ja_~WP zD_nW(^k;aA^bTA}4Bm_0hi^vQIrw3ik&41!G15eMrydD|=OR}AKHY5~;VQVcRjk1c z4Pp`%ftV2_iB(C*ai|(sCOAeGc`aL3mL+u}_bdxHob&XkK|3HCsGS>K13)o=4s(o^ zoT_o;NVD;(wjN8c-{+Y(udXgu&wrXjS*CZ+C~FJPECwnJtiJ3R8B;Ytg@D4Bfa?9a z2LOd)VEG5c`Ivemp#a4JP$&tN1oVNR-(Of<>@V~e770bg@(c2g5D11sB|&&7^s^;Q zQLwm(4KPSMNc>rFDTBmL^Ju=-;pR$xO^hp@QW~-y`dn_$=s3Dm%Xa@ImBp2_H;@rk z<6h19f)JJVVq)o}ZTK59Tqhcpu~p)mQEpp^-y_sZhyZlz3+_DpL*2tfg9asOG8Dkn z;YVTgS-J1xXLV7E+;*`Rmz0PB84a1|9778c2PFsxT#Z3xnxDt!{4 zhz2Rzeyd&2Fi443e@e#CAJT99>@XGy>M=hTEQ>ChLph{3p|@lv*v4IqpVK{|=)&FN zY(*D}NUxMG>HUR)K(M4Fkk!8+sDS|LK;H=lirFHDDnwSlp?qmXzsGQ1R46hI#8*{< z=SBfUc6oG9j0OwwgMdYx!clzEkPqx3B0YW`uGoYd@pFdH;Yuf%rgz|qUw8?>WvqoO zUC7Sp;fhcACVs>48@SR9pZOfFc!fXXmksOTN)OUABK@8R;CnuTE4|<%mV=c$XYgaz z!}_5*ast#`g+gK&mE?O7q-RhOW3;kE#uqdP0FuXvqAV;5X_X~Jl?6OVFfFS4Oy(WI zv4%8&JmUz{uB<04eP8;WX+v8>dD)D`2j)%f@EL>d+1~Ef=~o99;JfwF zxFRjijBTaWW>l+fbuDeRoT^ZqLYUs6B}8@6&nFl#eRP0J@?0dTAr7D zpGe>Cowk41g!vn9WN*6@ipD^y4Eq`FRTWwRF;8{1Sc4+@MqPk(sXWRQ7c*7Ux5F0pIbd>#aaS`1#SoXcHF2@5a4It^J#wQuZI9~Y9#Ij| ziGC`e6o?CyuojcVIplkWt04YFZ_pWPR&;@!oK#Le?{9ys>!=FF6HU`%%N&BolC;#8 zCYHOK_|OjNDe2aZ>E}zI%L4oG%8rBE8@x<=cv|1WbfwMYve-OjaW{#&ra@oMp*^ib ztHd%ndZj%zLQi>%nE`dOBj~N&#-U=8>QlSi3SJ!ua)8D%RFsNM%Jh6>2pbt8urYex z$eg2*-LaAjyubOe&{JzRpfMB;j;fqLBb4ri?=)bvF+KxBRy!rmV#y4YC z;r^W)%RIk-Od#4&m!1(@>eP8H4VLP%#Bx{D3zGF@UQfi)w(F+0yoP7)zwxb)Zz&5D z74(*|hprUQ-(H`O+roX*7o;j3Mowy{NM#9W4zt zR+d`z1x!8)Fi~d*Qs0f zqn>ib7<%CXOQ2A_Tqxx7GKi2vdv&lbk)9sw2X(MESgXtGmV43*{e_{*NO@7kaa>yn z^JUdWR(k#_pojWArahF=1G^jOf!(_B;>#y5+bO8P8w?;ERag>KLg5TLcRED>Y6>L!RS*D9XMc@zZP>6?L0VC{&`hr`7t%h7<`{RW@h{d5Hx2DJNlExzQt z*p5s3Yu&GU@=jmz4buB_palFETpHEF8o3Q(1)ecOoQbAQ=uX5!`p#q`R*`3PF|cHd z;ifQY8^=Vr!d7M|2RsxFDdQod0xAL=nxWN!88UqYp^L;aK+4Z!4?^uQWc(r|45Fn% z8h?ejFEDv@Mr*?V;`G44eN~MU=Xmf3pT8YxkRE<*_Z2T3UOc75{9McWiOrY3;lKIx zKB7cj_c<4*v^&d2I!dZ3Q3~T zgql4VP;#jX+yQxFTMqprjlue{02bD@msB*QSKhUvJ+kxBo=XQNNxQF@oo?xv;ewhU z{_=)~#VfCAUWv<|#KwcC{xB-gINnwm_gXA@?((lmbDrFK@{;RrTU2tOMEbbcX_8MlprzYbx`-&ho;1ugzkB>=@)t>zERla^%7= zU#w)TqU?k@6Lox+?5YbJ8ifY6|A#"?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> 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