change on broker (organization type) - some changes on livestock & herd

This commit is contained in:
2025-08-05 16:33:42 +03:30
parent 7792e67b1e
commit 2bc1931def
11 changed files with 267 additions and 4 deletions

View File

@@ -0,0 +1,94 @@
import pandas as pd
from django.core.management.base import BaseCommand
from apps.herd.models import Rancher
from apps.herd.models import Herd
from apps.authentication.models import Province, City, Organization
class Command(BaseCommand):
help = "Import Rancher and Herd data from Excel"
def add_arguments(self, parser):
parser.add_argument('excel_path', type=str)
def handle(self, *args, **options):
path = options['excel_path']
df = pd.read_excel(path)
records = df.to_dict(orient='records')
self.stdout.write(self.style.SUCCESS(f"{len(records)} records loaded."))
ranchers_to_create = []
herds_to_create = []
province_cache = {p.id: p for p in Province.objects.all()}
city_cache = {c.id: c for c in City.objects.all()}
org_cache = {o.id: o for o in Organization.objects.all()}
for r in records:
full_name = str(r.get("fullname") or "").strip()
first_name = full_name.split(" ")[0] if full_name else ""
last_name = " ".join(full_name.split(" ")[1:]) if len(full_name.split(" ")) > 1 else ""
# province = province_cache.get((Province.objects.get(name=r.get("province"))).id)
province = Province.objects.get(id=1)
city = City.objects.get(id=1)
rancher = Rancher(
first_name=first_name,
last_name=last_name,
mobile=r.get("mobile"),
national_code=r.get("national_id"),
address="",
province=province,
city=city,
without_herd=not bool(r.get("herd_code"))
)
ranchers_to_create.append(rancher)
# ذخیره‌ی دامداران
Rancher.objects.bulk_create(ranchers_to_create, batch_size=10000)
self.stdout.write(self.style.SUCCESS(f"✅ Created {len(ranchers_to_create)} ranchers."))
# بازیابی مجدد همه‌ی دامداران برای نگاشت herd
rancher_cache = {r.national_code: r for r in Rancher.objects.all()}
for r in records:
if not r.get("herd_code"):
print("not herd code")
continue
province = Province.objects.get(id=1)
city = City.objects.get(id=1)
coop = Organization.objects.get(id=1)
print(f"province {province}")
print(f"city {city}")
print(f"coop {coop}")
key = r.get("national_id")
print(f'key {key}')
rancher = Rancher.objects.get(national_code=key)
print(f'ranchers {rancher}')
if not rancher:
print("not rancher")
continue
herd = Herd(
code=r.get("herd_code"),
name=r.get("herd_name"),
rancher=rancher,
province=province,
city=city,
postal=r.get("postal_code"),
institution=r.get("unit_id"),
epidemiologic=r.get("epidemiological_code"),
cooperative=coop,
heavy_livestock_number=r.get("heavy_livestock") or 0,
light_livestock_number=r.get("light_livestock") or 0,
)
print(herd)
herds_to_create.append(herd)
print(herds_to_create)
Herd.objects.bulk_create(herds_to_create, batch_size=10000)
self.stdout.write(self.style.SUCCESS(f"✅ Created {len(herds_to_create)} herds."))

View File

@@ -151,7 +151,7 @@ class RancherViewSet(viewsets.ModelViewSet, DynamicSearchMixin):
""" list of rancher herds """
rancher = self.get_object()
queryset = rancher.herd.all() # get rancher herds
queryset = rancher.herd.all().order_by('-modify_date') # get rancher herds
# paginate queryset
page = self.paginate_queryset(queryset)

View File

@@ -0,0 +1,86 @@
import pandas as pd
from django.core.management.base import BaseCommand
from django.utils.dateparse import parse_datetime
from apps.livestock.models import LiveStock, LiveStockType, LiveStockSpecies
from apps.herd.models import Herd
from apps.tag.models import Tag
class Command(BaseCommand):
help = "Import livestock data from Excel"
def add_arguments(self, parser):
parser.add_argument('excel_path', type=str)
def handle(self, *args, **options):
path = options['excel_path']
df = pd.read_excel(path)
records = df.to_dict(orient='records')
self.stdout.write(self.style.SUCCESS(f"{len(records)} records loaded."))
herd_cache = {h.code: h for h in Herd.objects.all()}
type_cache = {t.name.strip(): t for t in LiveStockType.objects.all()}
species_male = LiveStockSpecies.objects.filter(name__icontains='نر').first()
species_female = LiveStockSpecies.objects.filter(name__icontains='ماده').first()
livestocks_to_create = []
skipped = 0
for r in records:
try:
herd_code = str(r.get('herd_code')).strip()
if not herd_code:
skipped += 1
continue
herd = herd_cache.get(herd_code)
if not herd:
herd = Herd.objects.create(
code=herd_code,
name=f"گله {herd_code}",
province_id=int(r.get('province_id')) if r.get('province_id') else None,
city_id=int(r.get('city_id')) if r.get('city_id') else None,
cooperative_id=int(r.get('cooperative_id')) if r.get('cooperative_id') else None,
)
herd_cache[herd_code] = herd
tag_code = r.get('national_id_livestock_code')
tag = Tag.objects.filter(code=tag_code).first()
if not tag:
skipped += 1
continue
type_name = str(r.get('type')).strip()
livestock_type = type_cache.get(type_name)
if not livestock_type:
skipped += 1
continue
gender_str = str(r.get('gender')).strip()
gender = 1 if gender_str == 'نر' else 2 if gender_str == 'ماده' else None
species = species_male if gender == 1 else species_female
birthdate = parse_datetime(str(r.get('birth_day_gh'))) if r.get('birth_day_gh') else None
weight_type = 'H' if type_name == 'گاو' else 'L'
livestocks_to_create.append(LiveStock(
herd=herd,
tag=tag,
type=livestock_type,
use_type=None,
species=species,
weight_type=weight_type,
gender=gender,
birthdate=birthdate
))
except Exception as e:
skipped += 1
print(e)
continue
LiveStock.objects.bulk_create(livestocks_to_create, batch_size=10000)
self.stdout.write(self.style.SUCCESS(f"✅ Created {len(livestocks_to_create)} records."))
self.stdout.write(self.style.WARNING(f"⚠️ Skipped {skipped} records due to missing/invalid data."))

View File

@@ -1,9 +1,11 @@
from rest_framework import viewsets
from apps.livestock import models as livestock_models
from apps.tag.web.api.v1.api import TagViewSet
from . import serializers as livestock_serializers
from rest_framework.exceptions import APIException
from rest_framework.decorators import action
from rest_framework.response import Response
from common.tools import CustomOperations
from django.db import transaction
from rest_framework import status

View File

@@ -0,0 +1,19 @@
# Generated by Django 5.0 on 2025-08-05 12:38
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pos_device', '0027_alter_deviceactivationcode_expires_at'),
]
operations = [
migrations.AlterField(
model_name='deviceactivationcode',
name='expires_at',
field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 16, 8, 12, 82964)),
),
]

View File

@@ -0,0 +1,19 @@
# Generated by Django 5.0 on 2025-08-05 12:40
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pos_device', '0028_alter_deviceactivationcode_expires_at'),
]
operations = [
migrations.AlterField(
model_name='deviceactivationcode',
name='expires_at',
field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 16, 10, 58, 428777)),
),
]

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.0 on 2025-08-05 12:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('product', '0065_productstats_given_distribution_number'),
]
operations = [
migrations.RemoveField(
model_name='broker',
name='organization',
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 5.0 on 2025-08-05 12:40
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0027_remove_organizationstats_total_buyers_and_more'),
('product', '0066_remove_broker_organization'),
]
operations = [
migrations.AddField(
model_name='broker',
name='organization_type',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_organization', to='authentication.organizationtype'),
),
]

View File

@@ -3,7 +3,7 @@ from simple_history.models import HistoricalRecords
from django.db import models
from apps.core.models import BaseModel
from apps.authorization.models import UserRelations
from apps.authentication.models import Organization
from apps.authentication.models import OrganizationType, Organization
from django.contrib.postgres.fields import ArrayField
from apps.livestock.models import LiveStockType
from datetime import datetime
@@ -238,8 +238,8 @@ class Broker(BaseModel):
related_name='product_broker',
null=True
)
organization = models.ForeignKey(
Organization,
organization_type = models.ForeignKey(
OrganizationType,
on_delete=models.CASCADE,
related_name='product_organization',
null=True

View File

@@ -19,6 +19,11 @@ class TagSerializer(serializers.ModelSerializer):
'organization',
'status',
]
extra_kwargs = {
'serial': {
'required': False
}
}
def update(self, instance, validated_data):
""" update tag information """

View File

@@ -48,6 +48,7 @@ pyOpenSSL
pyparsing
python-dateutil
pytz
pandas
redis
requests
rsa==4.8