diff --git a/Rasaddam_Backend/settings.py b/Rasaddam_Backend/settings.py index 25aad7a..4b7bd45 100644 --- a/Rasaddam_Backend/settings.py +++ b/Rasaddam_Backend/settings.py @@ -75,6 +75,7 @@ INSTALLED_APPS = [ MIDDLEWARE = [ # 'elasticapm.contrib.django.middleware.TracingMiddleware', + 'apps.core.custom_middlewares.request_middleware.RequestMiddleware', 'apps.core.middlewares.Json500Middleware', 'corsheaders.middleware.CorsMiddleware', # noqa 'django.middleware.security.SecurityMiddleware', diff --git a/apps/core/custom_middlewares/__init__.py b/apps/core/custom_middlewares/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/core/custom_middlewares/request_middleware.py b/apps/core/custom_middlewares/request_middleware.py new file mode 100644 index 0000000..ea7b037 --- /dev/null +++ b/apps/core/custom_middlewares/request_middleware.py @@ -0,0 +1,17 @@ +import threading + +_local = threading.local() + + +def get_current_request_body(): + return getattr(_local, "request_body", None) + + +class RequestMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + _local.request_body = request.body + response = self.get_response(request) + return response diff --git a/apps/product/migrations/0101_quota_edited_pricing_features.py b/apps/product/migrations/0101_quota_edited_pricing_features.py new file mode 100644 index 0000000..b4296bf --- /dev/null +++ b/apps/product/migrations/0101_quota_edited_pricing_features.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0 on 2025-12-02 10:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0100_attributevalue_org_quota_stat_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='quota', + name='edited_pricing_features', + field=models.BooleanField(default=False, help_text='True when quota broker values & attribute values changed in distribution of quota'), + ), + ] diff --git a/apps/product/models.py b/apps/product/models.py index db3cf33..2bfd223 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -418,6 +418,10 @@ class Quota(BaseModel): pre_sale_balance = models.IntegerField(default=0) free_sale = models.BooleanField(default=False) free_sale_balance = models.IntegerField(default=0) + edited_pricing_features = models.BooleanField( + default=False, + help_text='True when quota broker values & attribute values changed in distribution of quota' + ) def __str__(self): return f"Quota ({self.id}) for {self.product.name}" @@ -853,9 +857,13 @@ class QuotaDistribution(BaseModel): def pre_sale(self): return self.quota.pre_sale - def save(self, *args, **kwargs): + def save(self, additional_data=None, *args, **kwargs): if not self.distribution_id: self.distribution_id = self.generate_distribution_id() + + if additional_data: + self.additional_data = additional_data + print(self.additional_data) return super(QuotaDistribution, self).save(*args, **kwargs) diff --git a/apps/product/pos/api/v1/serializers/product_serializers.py b/apps/product/pos/api/v1/serializers/product_serializers.py index 3eeb0b8..341423b 100644 --- a/apps/product/pos/api/v1/serializers/product_serializers.py +++ b/apps/product/pos/api/v1/serializers/product_serializers.py @@ -130,6 +130,7 @@ class AttributeValueSerializer(serializers.ModelSerializer): fields = [ "id", "quota", + "org_quota_stat", "attribute", "value", ] diff --git a/apps/product/pos/api/v1/serializers/quota_serializers.py b/apps/product/pos/api/v1/serializers/quota_serializers.py index ef62abd..eaab56c 100644 --- a/apps/product/pos/api/v1/serializers/quota_serializers.py +++ b/apps/product/pos/api/v1/serializers/quota_serializers.py @@ -140,6 +140,7 @@ class QuotaBrokerValueSerializer(serializers.ModelSerializer): # noqa fields = [ "id", "quota", + "org_quota_stat", "broker", "value", ] diff --git a/apps/product/services/quota_stat_service.py b/apps/product/services/quota_stat_service.py index cd2dd9e..dea053e 100644 --- a/apps/product/services/quota_stat_service.py +++ b/apps/product/services/quota_stat_service.py @@ -1,14 +1,51 @@ -from apps.product.models import QuotaDistribution, OrganizationQuotaStats +import json + +from apps.core.custom_middlewares.request_middleware import get_current_request_body +from apps.product.models import QuotaDistribution, OrganizationQuotaStats, AttributeValue, Attribute, QuotaBrokerValue, \ + Broker from apps.product.validators.quota_stats_validator import QuotaStatsValidator from apps.warehouse.models import InventoryEntry +def import_price_features(data, assigned_stat, quota): + """ + create price attributes data & broker pricing value for every distribution + """ + assigned_stat.attribute_values.all().delete() + assigned_stat.broker_values.all().delete() + + if 'price_attributes_data' and 'broker_data' in data.keys(): + attr_price_values = [AttributeValue( + attribute=Attribute.objects.get(id=attr['attribute']), + value=attr['value'], + quota=quota, + org_quota_stat=assigned_stat + ) for attr in data['price_attributes_data']] + AttributeValue.objects.bulk_create(attr_price_values) # bulk create + + broker_price_values = [ + QuotaBrokerValue( + quota=quota, + broker=Broker.objects.get(id=broker['broker']), + value=broker['value'], + org_quota_stat=assigned_stat + ) for broker in data['broker_data'] + ] + QuotaBrokerValue.objects.bulk_create(broker_price_values) # bulk create + + quota.edited_pricing_features = True + quota.save(update_fields=['edited_pricing_features']) + + class QuotaStatsService: @staticmethod def apply_distribution(distribution: QuotaDistribution): quota = distribution.quota # origin org assigner = distribution.assigner_organization + if assigner.type.key == 'ADM': + assigner = quota.registerer_organization + # destination org assigned = distribution.assigned_organization @@ -23,12 +60,10 @@ class QuotaStatsService: organization=assigner, quota=quota, ) - print(assigner_stat.id) if created: assigner_stat.stat_type = 'distribution' assigner_stat.save() if assigner_stat.stat_type == 'distribution': - print(assigner_stat.remaining_amount) assigner_stat.remaining_amount -= distribution.weight assigner_stat.total_distributed += distribution.weight assigner_stat.save() @@ -39,12 +74,15 @@ class QuotaStatsService: quota=quota, stat_type='distribution' ) - print(distribution._request) # noqa assigned_stat.total_amount += distribution.weight assigned_stat.remaining_amount += distribution.weight assigned_stat.distributions.add(distribution) assigned_stat.save() + # create pricing attributes and broker pricing data + data = json.loads(get_current_request_body().decode()) + import_price_features(data, assigned_stat, quota) + @staticmethod def update_distribution(distribution: QuotaDistribution, old_weight: int): diff = distribution.weight - old_weight @@ -81,6 +119,10 @@ class QuotaStatsService: assigned_stat.remaining_amount += diff assigned_stat.save() + # create pricing attributes and broker pricing data + data = json.loads(get_current_request_body().decode()) + import_price_features(data, assigned_stat, quota) + @staticmethod def delete_distribution(distribution: QuotaDistribution): quota = distribution.quota diff --git a/apps/product/web/api/v1/viewsets/quota_distribution_api.py b/apps/product/web/api/v1/viewsets/quota_distribution_api.py index 1cbefe2..fa9e2a6 100644 --- a/apps/product/web/api/v1/viewsets/quota_distribution_api.py +++ b/apps/product/web/api/v1/viewsets/quota_distribution_api.py @@ -60,20 +60,19 @@ class QuotaDistributionViewSet(BaseViewSet, SoftDeleteMixin, viewsets.ModelViewS except APIException as e: raise APIException("unauthorized", code=status.HTTP_401_UNAUTHORIZED) - price_attributes_data = request.data.pop('price_attributes_data') - broker_data = request.data.pop('broker_data') + price_attributes_data = request.data.pop( + 'price_attributes_data' + ) if 'price_attributes_data' in request.data.keys() else None + + broker_data = request.data.pop( + 'broker_data' + ) if 'broker_data' in request.data.keys() else None request.data.update({'assigner_organization': assigner_user.organization.id}) serializer = self.serializer_class(data=request.data) if serializer.is_valid(): distribution = serializer.save() - # to use in signals - distribution._request = { - 'price_attributes_data': price_attributes_data, - 'broker_data': broker_data - } - # add this organization to quota assigned_organizations # this org is received a distribution from quota distribution.quota.assigned_organizations.add(distribution.assigned_organization)