import --> create tag distribution with/without batch
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
# Generated by Django 5.0 on 2026-01-20 07:31
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0060_organization_ownership_code'),
|
||||
('tag', '0036_tagdistribution_assigner_org_and_more'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='tagdistribution',
|
||||
name='dist_identity',
|
||||
field=models.CharField(default='0', max_length=20, null=True, unique=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tagdistribution',
|
||||
name='is_closed',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tagbatch',
|
||||
name='tag',
|
||||
field=models.ManyToManyField(related_name='batches', to='tag.tag'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TagDistributionBatch',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('creator_info', models.CharField(max_length=100, null=True)),
|
||||
('modifier_info', models.CharField(max_length=100, null=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('dist_batch_identity', models.CharField(default='0', max_length=20, null=True, unique=True)),
|
||||
('total_tag_count', models.IntegerField(default=0)),
|
||||
('is_closed', models.BooleanField(default=False)),
|
||||
('assigned_org', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='to_tag_distribution_batch', to='authentication.organization')),
|
||||
('assigner_org', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='from_tag_distribution_batch', to='authentication.organization')),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_createddby', to=settings.AUTH_USER_MODEL)),
|
||||
('distributions', models.ManyToManyField(related_name='tag_distribution_batch', to='tag.tagdistribution')),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='%(class)s_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -65,7 +65,7 @@ class TagBatch(BaseModel):
|
||||
null=True
|
||||
)
|
||||
|
||||
tag = models.ManyToManyField(Tag, related_name='tags')
|
||||
tag = models.ManyToManyField(Tag, related_name='batches')
|
||||
species_code = models.IntegerField(default=0)
|
||||
serial_from = models.PositiveBigIntegerField(default=0)
|
||||
serial_to = models.PositiveBigIntegerField(default=0)
|
||||
@@ -89,6 +89,7 @@ class TagBatch(BaseModel):
|
||||
|
||||
|
||||
class TagDistribution(BaseModel):
|
||||
dist_identity = models.CharField(max_length=20, default="0", unique=True, null=True)
|
||||
batch = models.ForeignKey(
|
||||
TagBatch,
|
||||
on_delete=models.CASCADE,
|
||||
@@ -110,6 +111,7 @@ class TagDistribution(BaseModel):
|
||||
)
|
||||
species_code = models.IntegerField(default=0)
|
||||
distributed_number = models.IntegerField(default=0)
|
||||
is_closed = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.id}-{self.distributed_number}-{self.assigned_org.name}'
|
||||
@@ -118,6 +120,31 @@ class TagDistribution(BaseModel):
|
||||
return super(TagDistribution, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TagDistributionBatch(BaseModel):
|
||||
dist_batch_identity = models.CharField(max_length=20, default="0", unique=True, null=True)
|
||||
assigner_org = models.ForeignKey(
|
||||
Organization,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='from_tag_distribution_batch',
|
||||
null=True
|
||||
)
|
||||
assigned_org = models.ForeignKey(
|
||||
Organization,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="to_tag_distribution_batch",
|
||||
null=True
|
||||
)
|
||||
distributions = models.ManyToManyField(TagDistribution, related_name='tag_distribution_batch')
|
||||
total_tag_count = models.IntegerField(default=0)
|
||||
is_closed = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.id}'
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
return super(TagDistributionBatch, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TagAssignment(BaseModel):
|
||||
organization = models.ForeignKey(
|
||||
auth_models.Organization,
|
||||
|
||||
@@ -1,6 +1,83 @@
|
||||
import random
|
||||
|
||||
from django.db import transaction
|
||||
|
||||
from apps.authentication.models import Organization
|
||||
from apps.tag.exceptions import TagException
|
||||
from apps.tag.models import Tag, TagBatch, TagDistribution, TagDistributionBatch
|
||||
from common.generics import generate_unique_code
|
||||
|
||||
|
||||
class TagDistributionService:
|
||||
"""
|
||||
service of distribute tags in organizations
|
||||
"""
|
||||
|
||||
pass
|
||||
def create_distribution(self, org: Organization = None, data: dict = None):
|
||||
"""
|
||||
distribute tags with batch
|
||||
"""
|
||||
with transaction.atomic():
|
||||
distributions = []
|
||||
total_counted_tags = 0
|
||||
assigned_org = Organization.objects.get(id=data.get('assigned_org'))
|
||||
|
||||
for distribution in data.get('dists'):
|
||||
batch_identity = distribution.get('batch_identity', None)
|
||||
# if batch identity exists distribute tags of batch
|
||||
if batch_identity:
|
||||
batch = TagBatch.objects.get(batch_identity=batch_identity)
|
||||
tags = Tag.objects.filter(
|
||||
batches__batch_identity=batch_identity,
|
||||
species_code=distribution.get('species_code'),
|
||||
status='F'
|
||||
)
|
||||
else:
|
||||
batch = None
|
||||
# get tags without batch and only with species code
|
||||
tags = Tag.objects.filter(
|
||||
species_code=distribution.get('species_code'),
|
||||
status='F'
|
||||
)
|
||||
|
||||
if tags.count() < distribution.get('count'):
|
||||
raise TagException(
|
||||
"تعداد وارد شده از تعداد موجودی این گونه بیشتر میباشد.", # noqa
|
||||
403
|
||||
)
|
||||
|
||||
dist = TagDistribution.objects.create(
|
||||
batch=batch,
|
||||
assigner_org=org,
|
||||
assigned_org=assigned_org,
|
||||
species_code=distribution.get('species_code'),
|
||||
distributed_number=distribution.get('count'),
|
||||
dist_identity=generate_unique_code(f"{random.randint(1000, 9999)}"),
|
||||
)
|
||||
|
||||
# get counted tag ids and filter by them to update status To Reserve
|
||||
counted_tags_obj = tags.order_by('create_date')[:int(distribution.get('count'))]
|
||||
counted_tag_ids = [tag.id for tag in counted_tags_obj]
|
||||
tags.filter(id__in=counted_tag_ids).update(status='R')
|
||||
|
||||
dist.tag.add(*counted_tags_obj)
|
||||
distributions.append(dist)
|
||||
|
||||
total_counted_tags += distribution.get('count')
|
||||
|
||||
# create distribution batch
|
||||
distributions_batch = TagDistributionBatch.objects.create(
|
||||
assigner_org=org,
|
||||
assigned_org=assigned_org,
|
||||
total_tag_count=total_counted_tags,
|
||||
dist_batch_identity=generate_unique_code(f"{random.randint(1000, 9999)}"),
|
||||
)
|
||||
distributions_batch.distributions.add(*distributions)
|
||||
|
||||
return {'tag_distributions': distributions, 'distributions_batch': distributions_batch}
|
||||
|
||||
def edit_distribution(self):
|
||||
"""
|
||||
edit record of distributed tags
|
||||
"""
|
||||
pass
|
||||
|
||||
@@ -16,6 +16,7 @@ from apps.core.mixins.soft_delete_mixin import SoftDeleteMixin
|
||||
from apps.tag import exceptions as tag_exceptions
|
||||
from apps.tag import models as tag_models
|
||||
from apps.tag.models import TagBatch
|
||||
from apps.tag.services.tag_distribution_services import TagDistributionService
|
||||
from apps.tag.services.tag_services import TagService
|
||||
from common.helpers import get_organization_by_user
|
||||
from common.liara_tools import upload_to_liara
|
||||
@@ -344,7 +345,13 @@ class TagBatchViewSet(BaseViewSet, SoftDeleteMixin, DynamicSearchMixin, viewsets
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class TagDistributionViewSet(BaseViewSet, SoftDeleteMixin, DynamicSearchMixin, viewsets.ModelViewSet):
|
||||
class TagDistributionViewSet(
|
||||
BaseViewSet,
|
||||
SoftDeleteMixin,
|
||||
DynamicSearchMixin,
|
||||
viewsets.ModelViewSet,
|
||||
TagDistributionService
|
||||
):
|
||||
queryset = tag_models.TagDistribution.objects.all()
|
||||
serializer_class = TagDistributionSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
@@ -369,3 +376,18 @@ class TagDistributionViewSet(BaseViewSet, SoftDeleteMixin, DynamicSearchMixin, v
|
||||
serializer = self.get_serializer(page, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
return Response(self.serializer_class(queryset).data)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
"""
|
||||
create tag distributions with batch or without batch in random
|
||||
"""
|
||||
org = get_organization_by_user(request.user)
|
||||
data = request.data.copy()
|
||||
|
||||
distribution_data = self.create_distribution(
|
||||
org=org,
|
||||
data=data
|
||||
)
|
||||
|
||||
serializer = self.serializer_class(distribution_data.get('tag_distributions'), many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
@@ -4,7 +4,7 @@ from rest_framework.routers import DefaultRouter
|
||||
from .api import (
|
||||
TagViewSet,
|
||||
TagAssignmentViewSet,
|
||||
AllocatedTagsViewSet, TagBatchViewSet
|
||||
AllocatedTagsViewSet, TagBatchViewSet, TagDistributionViewSet
|
||||
)
|
||||
|
||||
router = DefaultRouter()
|
||||
@@ -12,6 +12,7 @@ router.register(r'tag', TagViewSet, basename='tag')
|
||||
router.register(r'tag_assignment', TagAssignmentViewSet, basename='tag_assignment')
|
||||
router.register(r'allocated_tag', AllocatedTagsViewSet, basename='allocated_tag')
|
||||
router.register(r'tag_batch', TagBatchViewSet, basename='tag_batch')
|
||||
router.register(r'tag_distribution', TagDistributionViewSet, basename='tag_distribution')
|
||||
|
||||
urlpatterns = [
|
||||
path('v1/', include(router.urls))
|
||||
|
||||
Reference in New Issue
Block a user