Files
2026-01-28 16:18:10 +03:30

9557 lines
445 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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_kill_req_manual(request):
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)
return HttpResponse('ok')
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,to_cold_house__isnull=True).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)
def archive_kill_house_remain_limitation_weight_manual(request):
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)
return HttpResponse('ok')
def delete_steward_allocation_manual(request):
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)
return HttpResponse('ok')
def delete_sale_bar_manual(request):
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)
def send_credit_sahandsms_sms_manual(request):
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)
return HttpResponse('ok')