diff --git a/apps/product/migrations/0039_alter_saleunit_unit.py b/apps/product/migrations/0039_alter_saleunit_unit.py new file mode 100644 index 0000000..20bfa6b --- /dev/null +++ b/apps/product/migrations/0039_alter_saleunit_unit.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0 on 2025-07-08 11:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0038_attribute_type_broker_calculation_strategy'), + ] + + operations = [ + migrations.AlterField( + model_name='saleunit', + name='unit', + field=models.CharField(max_length=250, null=True, unique=True), + ), + ] diff --git a/apps/product/migrations/0040_remove_saleunit_variation_coefficient.py b/apps/product/migrations/0040_remove_saleunit_variation_coefficient.py new file mode 100644 index 0000000..15460ad --- /dev/null +++ b/apps/product/migrations/0040_remove_saleunit_variation_coefficient.py @@ -0,0 +1,17 @@ +# Generated by Django 5.0 on 2025-07-08 12:15 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0039_alter_saleunit_unit'), + ] + + operations = [ + migrations.RemoveField( + model_name='saleunit', + name='variation_coefficient', + ), + ] diff --git a/apps/product/models.py b/apps/product/models.py index 404d8ef..de48a4b 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -232,12 +232,11 @@ class SaleUnit(BaseModel): related_name='sale_unit', null=True ) - unit = models.CharField(max_length=250, null=True) - variation_coefficient = models.IntegerField(default=0) + unit = models.CharField(max_length=250, null=True, unique=True) required = models.BooleanField(default=False) def __str__(self): - return f'{self.product.name} - {self.unit} - {self.variation_coefficient}' + return f'{self.product.name} - {self.unit}' def save(self, *args, **kwargs): return super(SaleUnit, self).save(*args, **kwargs) diff --git a/apps/product/web/__init__.py b/apps/product/web/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/product/web/api/v1/serializers/__init__.py b/apps/product/web/api/v1/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/product/web/api/v1/product_serializers.py b/apps/product/web/api/v1/serializers/product_serializers.py similarity index 100% rename from apps/product/web/api/v1/product_serializers.py rename to apps/product/web/api/v1/serializers/product_serializers.py diff --git a/apps/product/web/api/v1/quota_distribution_serializers.py b/apps/product/web/api/v1/serializers/quota_distribution_serializers.py similarity index 94% rename from apps/product/web/api/v1/quota_distribution_serializers.py rename to apps/product/web/api/v1/serializers/quota_distribution_serializers.py index 4373e12..aa8976a 100644 --- a/apps/product/web/api/v1/quota_distribution_serializers.py +++ b/apps/product/web/api/v1/serializers/quota_distribution_serializers.py @@ -1,13 +1,12 @@ from rest_framework import serializers from apps.product import models as product_models -from apps.product.web.api.v1.product_serializers import QuotaSerializer +from apps.product.web.api.v1.serializers.product_serializers import QuotaSerializer from django.db import models from apps.product.exceptions import ( QuotaWeightException, QuotaClosedException, QuotaExpiredTimeException ) -from rest_framework import status class QuotaDistributionSerializer(serializers.ModelSerializer): diff --git a/apps/product/web/api/v1/urls.py b/apps/product/web/api/v1/urls.py index 264537b..f2e5251 100644 --- a/apps/product/web/api/v1/urls.py +++ b/apps/product/web/api/v1/urls.py @@ -1,5 +1,4 @@ -from apps.product.web.api.v1 import quota_distribution_api as distribution_apis -from apps.product.web.api.v1 import product_api as api_views +from apps.product.web.api.v1.viewsets import product_api as api_views, quota_distribution_api as distribution_apis from rest_framework.routers import DefaultRouter from django.urls import path, include diff --git a/apps/product/web/api/v1/viewsets/__init__.py b/apps/product/web/api/v1/viewsets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/product/web/api/v1/product_api.py b/apps/product/web/api/v1/viewsets/product_api.py similarity index 99% rename from apps/product/web/api/v1/product_api.py rename to apps/product/web/api/v1/viewsets/product_api.py index d0ac79f..5dcb091 100644 --- a/apps/product/web/api/v1/product_api.py +++ b/apps/product/web/api/v1/viewsets/product_api.py @@ -1,6 +1,6 @@ import datetime -from apps.product.web.api.v1 import product_serializers as product_serializers +from apps.product.web.api.v1.serializers import product_serializers as product_serializers from apps.product.exceptions import QuotaExpiredTimeException from apps.product.services import get_products_in_warehouse from common.helpers import get_organization_by_user @@ -82,48 +82,6 @@ class ProductViewSet(viewsets.ModelViewSet): serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) - @action( - methods=['get'], - detail=False, - url_path='quotas_statistics', - url_name='quotas_statistics', - name='quotas_statistics' - ) - @transaction.atomic - def quotas_statistics_by_product(self, request): - """ quota statistics of each product in organization warehouse """ - - product_data = [] - - organization = get_organization_by_user(request.user) - products = get_products_in_warehouse(organization.id) - - for product in products: - product_data.append(product.quota_information()) - - return Response(product_data, status=status.HTTP_200_OK) - - @action( - methods=['get'], - detail=True, - url_path='quotas_information', - url_name='quotas_information', - name='quotas_information' - ) - @transaction.atomic - def quotas_information_by_product(self, request, pk=None): - """ get quotas information of a product """ - - quotas = product_models.Quota.objects.select_related('product').filter( - product_id=pk, is_closed=False - ) - - try: - quota_serializer = product_serializers.QuotaSerializer(quotas, many=True).data - return Response(quota_serializer, status=status.HTTP_200_OK) - except APIException as e: - raise APIException(detail="data error", code=400) - @action( methods=['put'], detail=True, @@ -611,6 +569,7 @@ class QuotaViewSet(viewsets.ModelViewSet): # noqa ) def quotas_list_for_assigner(self, request): """ list of quotas for creator """ + assigner = product_models.UserRelations.objects.filter(user=request.user).first() serializers = self.serializer_class( self.queryset.filter(registerer_organization=assigner.organization), @@ -627,6 +586,7 @@ class QuotaViewSet(viewsets.ModelViewSet): # noqa ) def quotas_list_for_assigned(self, request): """ list of quotas for assigned organizations """ + assigned = product_models.UserRelations.objects.filter(user=request.user).first() serializer = self.serializer_class( self.queryset.filter(assigned_organizations=assigned.organization), @@ -635,6 +595,48 @@ class QuotaViewSet(viewsets.ModelViewSet): # noqa return Response(serializer.data, status=status.HTTP_200_OK) + @action( + methods=['get'], + detail=False, + url_path='quotas_statistics', + url_name='quotas_statistics', + name='quotas_statistics' + ) + @transaction.atomic + def quotas_statistics_by_product(self, request): + """ quota statistics of each product in organization warehouse """ + + product_data = [] + + organization = get_organization_by_user(request.user) + products = get_products_in_warehouse(organization.id) + + for product in products: + product_data.append(product.quota_information()) + + return Response(product_data, status=status.HTTP_200_OK) + + @action( + methods=['get'], + detail=True, + url_path='quotas_information', + url_name='quotas_information', + name='quotas_information' + ) + @transaction.atomic + def quotas_information_by_product(self, request, pk=None): + """ get quotas information of a product """ + + quotas = self.queryset.select_related('product').filter( + product_id=pk, is_closed=False + ) + + try: + quota_serializer = self.serializer_class(quotas, many=True).data + return Response(quota_serializer, status=status.HTTP_200_OK) + except APIException as e: + raise APIException(detail="data error", code=400) + @action( methods=['put'], detail=True, diff --git a/apps/product/web/api/v1/quota_distribution_api.py b/apps/product/web/api/v1/viewsets/quota_distribution_api.py similarity index 94% rename from apps/product/web/api/v1/quota_distribution_api.py rename to apps/product/web/api/v1/viewsets/quota_distribution_api.py index e246c1b..72ab1f5 100644 --- a/apps/product/web/api/v1/quota_distribution_api.py +++ b/apps/product/web/api/v1/viewsets/quota_distribution_api.py @@ -1,14 +1,11 @@ -from apps.product.web.api.v1 import quota_distribution_serializers as distribution_serializers -from apps.product.web.api.v1 import product_serializers as product_serializers +from apps.product.web.api.v1.serializers import quota_distribution_serializers as distribution_serializers from rest_framework.exceptions import APIException from apps.product import models as product_models from rest_framework.response import Response from rest_framework.decorators import action -from common.tools import CustomOperations from rest_framework import viewsets from rest_framework import status from django.db import transaction -from django.db.models import Q def trash(queryset, pk): # noqa