diff --git a/apps/tag/migrations/0038_tagdistributionbatch_distribution_type_and_more.py b/apps/tag/migrations/0038_tagdistributionbatch_distribution_type_and_more.py new file mode 100644 index 0000000..576f5a1 --- /dev/null +++ b/apps/tag/migrations/0038_tagdistributionbatch_distribution_type_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0 on 2026-01-24 05:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ('tag', '0037_tagdistribution_dist_identity_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='tagdistributionbatch', + name='distribution_type', + field=models.CharField(choices=[('random', 'RANDOM'), ('batch', 'BATCH')], default='batch', max_length=20, + null=True), + ), + migrations.AddField( + model_name='tagdistributionbatch', + name='remaining_tag_count', + field=models.PositiveBigIntegerField(default=0), + ), + migrations.AddField( + model_name='tagdistributionbatch', + name='total_distributed_tag_count', + field=models.PositiveBigIntegerField(default=0), + ), + ] diff --git a/apps/tag/migrations/0039_tagbatch_total_distributed_tags.py b/apps/tag/migrations/0039_tagbatch_total_distributed_tags.py new file mode 100644 index 0000000..cd7fa24 --- /dev/null +++ b/apps/tag/migrations/0039_tagbatch_total_distributed_tags.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0 on 2026-01-24 06:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tag', '0038_tagdistributionbatch_distribution_type_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='tagbatch', + name='total_distributed_tags', + field=models.PositiveBigIntegerField(default=0), + ), + ] diff --git a/apps/tag/models.py b/apps/tag/models.py index 8374df7..c6e170b 100644 --- a/apps/tag/models.py +++ b/apps/tag/models.py @@ -69,6 +69,7 @@ class TagBatch(BaseModel): species_code = models.IntegerField(default=0) serial_from = models.PositiveBigIntegerField(default=0) serial_to = models.PositiveBigIntegerField(default=0) + total_distributed_tags = models.PositiveBigIntegerField(default=0) status = models.CharField( max_length=20, @@ -145,6 +146,8 @@ class TagDistributionBatch(BaseModel): ) distributions = models.ManyToManyField(TagDistribution, related_name='tag_distribution_batch') total_tag_count = models.IntegerField(default=0) + total_distributed_tag_count = models.PositiveBigIntegerField(default=0) + remaining_tag_count = models.PositiveBigIntegerField(default=0) is_closed = models.BooleanField(default=False) def __str__(self): diff --git a/apps/tag/services/tag_distribution_services.py b/apps/tag/services/tag_distribution_services.py index f792c5a..e6ccf7c 100644 --- a/apps/tag/services/tag_distribution_services.py +++ b/apps/tag/services/tag_distribution_services.py @@ -1,6 +1,7 @@ import random from django.db import transaction +from django.db.models import Sum from apps.authentication.models import Organization from apps.tag.exceptions import TagException @@ -147,3 +148,16 @@ class TagDistributionService: dist_batch.distributions.add(*distributions) return {'tag_distributions': distributions, 'distributions_batch': dist_batch} + + def distribution_batch_main_dashboard(self, org: Organization): + """ + distribution batch main page dashboard detail + """ + + distributions_batch = TagDistributionBatch.objects.prefetch_related('distributions') + + distributions_batch.aggregate( + total_tag_count=Sum('total_tag_count'), + total_distributed_tag_count=Sum('total_distributed_tag_count'), + remaining_tag_count=Sum('remaining_tag_count'), + ) diff --git a/apps/tag/web/api/v1/api.py b/apps/tag/web/api/v1/api.py index e283e89..3eefb0d 100644 --- a/apps/tag/web/api/v1/api.py +++ b/apps/tag/web/api/v1/api.py @@ -440,6 +440,27 @@ class TagDistributionViewSet( return Response(status=status.HTTP_200_OK) + @action( + methods=['get'], + detail=False, + url_path='close_distributions_list', + url_name='close_distributions_list', + name='close_distributions_list', + ) + def close_distributions_list(self, request): + """ + list of closed distributions + """ + + queryset = self.get_queryset(visibility_by_org_scope=True).filter(is_closed=True).order_by('-create_date') + queryset = self.filter_query(queryset) + + page = self.paginate_queryset(queryset) + if page is not None: # noqa + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + return Response(self.serializer_class(queryset).data) + class TagDistributionBatchViewSet( BaseViewSet, @@ -490,3 +511,24 @@ class TagDistributionBatchViewSet( dist_batch.distributions.all().update(is_closed=True) # close distributions of batch return Response(status=status.HTTP_200_OK) + + @action( + methods=['get'], + detail=False, + url_path='closed_tag_dist_batch_list', + url_name='closed_tag_dist_batch_list', + name='closed_tag_dist_batch_list', + ) + def close_tag_dist_batch_list(self, request): + """ + list of closed tag distributions batch + """ + + queryset = self.get_queryset(visibility_by_org_scope=True).filter(is_closed=True).order_by('create_date') + queryset = self.filter_query(self.filter_queryset(queryset)) + + page = self.paginate_queryset(queryset) + if page is not None: # noqa + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + return Response(self.serializer_class(queryset).data)