From 30e0e3462f655f827ff076a8e8ca709bdb995a73 Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Mon, 25 Aug 2025 15:56:09 +0500 Subject: [PATCH] add new api --- config/__init__.py | 3 ++ config/celery.py | 5 +-- config/conf/celery.py | 7 +++- config/conf/jazzmin.py | 9 ++-- config/conf/redis.py | 2 +- config/settings/base.py | 6 +-- core/apps/orders/serializers/order.py | 2 - core/apps/orders/serializers/party.py | 42 ++++++++++--------- core/apps/orders/tasks/order.py | 10 ++--- core/apps/wherehouse/serializers/inventory.py | 6 +-- .../apps/wherehouse/serializers/wherehouse.py | 8 ++-- core/apps/wherehouse/urls.py | 8 +++- core/apps/wherehouse/views/inventory.py | 25 +++++++++++ docker-compose.yaml | 7 ++-- docker/Dockerfile.web | 29 +++++++++---- 15 files changed, 108 insertions(+), 61 deletions(-) create mode 100644 core/apps/wherehouse/views/inventory.py diff --git a/config/__init__.py b/config/__init__.py index e69de29..cd04264 100644 --- a/config/__init__.py +++ b/config/__init__.py @@ -0,0 +1,3 @@ +from .celery import app as celery_app + +__all__ = ['celery_app'] diff --git a/config/celery.py b/config/celery.py index 2667b4b..d6958f3 100644 --- a/config/celery.py +++ b/config/celery.py @@ -1,11 +1,10 @@ import os - from celery import Celery os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.base') -app = Celery('config') +app = Celery('config', broker="redis://redis:6379", backend="redis://redis:6379") + app.config_from_object('django.conf:settings', namespace='CELERY') - app.autodiscover_tasks() diff --git a/config/conf/celery.py b/config/conf/celery.py index 231f9e3..8f788ee 100644 --- a/config/conf/celery.py +++ b/config/conf/celery.py @@ -1,6 +1,9 @@ from django.conf import settings -CELERY_BROKER_URL = 'redis://redis:6379/0' +CELERY_BROKER_URL = 'redis://redis:6379' +CELERY_RESULT_BACKEND = "redis://redis:6379" CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' -CELERY_TIMEZONE = settings.TIME_ZONE \ No newline at end of file +CELERY_TIMEZONE = settings.TIME_ZONE +CELERY_ENABLED = True + diff --git a/config/conf/jazzmin.py b/config/conf/jazzmin.py index 210b930..b1b3026 100644 --- a/config/conf/jazzmin.py +++ b/config/conf/jazzmin.py @@ -25,13 +25,13 @@ JAZZMIN_SETTINGS = { "show_sidebar": True, "navigation_expanded": True, "hide_apps": [], - "hide_models": ["auth.Group"], + "hide_models": ["auth.Group"], "order_with_respect_to": ["auth"], "custom_links": { "books": [{ - "name": "Make Messages", - "url": "make_messages", + "name": "Make Messages", + "url": "make_messages", "icon": "fas fa-comments", "permissions": ["books.view_book"] }] @@ -45,11 +45,10 @@ JAZZMIN_SETTINGS = { "default_icon_parents": "fas fa-chevron-circle-right", "default_icon_children": "fas fa-circle", - "related_modal_active": True, "use_google_fonts_cdn": True, "show_ui_builder": False, "changeform_format": "collapsible", "language_chooser": False, -} \ No newline at end of file +} diff --git a/config/conf/redis.py b/config/conf/redis.py index 7bdb75d..7632575 100644 --- a/config/conf/redis.py +++ b/config/conf/redis.py @@ -1,7 +1,7 @@ CACHES = { "default": { "BACKEND": 'django_redis.cache.RedisCache', - "LOCATION": 'redis://redis:6379', + "LOCATION": 'redis://redis:6379z', "TIMEOUT": 300, }, } diff --git a/config/settings/base.py b/config/settings/base.py index 16b0ead..df44e85 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -38,7 +38,6 @@ PACKAGES = [ 'rest_framework_simplejwt', 'corsheaders', 'cacheops', - # 'silk', ] DJANGO_APPS = [ @@ -100,7 +99,6 @@ DATABASES = { 'PASSWORD': env.str('POSTGRES_PASSWORD'), 'HOST': env.str('POSTGRES_HOST'), 'PORT': env.str('POSTGRES_PORT'), - 'CONN_MAX_AGE': 0 } } @@ -159,5 +157,5 @@ from config.conf.logs import * from config.conf.cors_headers import * from config.conf.drf_yasg import * from config.conf.jazzmin import * -from config.conf.redis import * -from config.conf.celery import * \ No newline at end of file +from config.conf.celery import * +from config.conf.redis import * \ No newline at end of file diff --git a/core/apps/orders/serializers/order.py b/core/apps/orders/serializers/order.py index b394667..ab5ae2e 100644 --- a/core/apps/orders/serializers/order.py +++ b/core/apps/orders/serializers/order.py @@ -81,8 +81,6 @@ class MultipleOrderCreateSerializer(serializers.Serializer): date=common_date, employee=self.context.get('user'), )) - create_inventory.delay(resource['wherehouse'],resource['quantity'],resource) - created_orders = Order.objects.bulk_create(orders) return created_orders diff --git a/core/apps/orders/serializers/party.py b/core/apps/orders/serializers/party.py index 07d1270..3c4e13c 100644 --- a/core/apps/orders/serializers/party.py +++ b/core/apps/orders/serializers/party.py @@ -6,6 +6,7 @@ from core.apps.orders.models import Party, PartyAmount, Order, DeletedParty from core.apps.orders.serializers.order import MultipleOrderAddSerializer, OrderListSerializer from core.apps.accounts.models import User from core.apps.counterparty.serializers.counterparty import CounterpartyListPartySerializer +from core.apps.orders.tasks.order import create_inventory from core.apps.shared.models import UsdCourse from core.apps.products.models import Product, Unity from core.apps.projects.models import Project, ProjectFolder @@ -33,7 +34,7 @@ class PartyCreateSerializer(serializers.Serializer): raise serializers.ValidationError("User not found") data['user'] = user return data - + def create(self, validated_data): with transaction.atomic(): resources = validated_data.pop('resources') @@ -50,12 +51,13 @@ class PartyCreateSerializer(serializers.Serializer): quantity=resource.get('quantity'), unit_amount=resource.get('unit_amount'), currency=resource.get('currency'), - amount=resource.get('amount'), + amount=resource.get('amount'), employee=self.context.get('user'), qqs_price=resource.get('qqs_price'), total_price=resource.get('total_price'), qqs=resource.get('qqs'), )) + create_inventory.delay(resource['wherehouse_id'], resource['quantity'], resource['product_id'], resource['unity_id'], resource['total_price']) if validated_data.get('currency') == 'uzs': if resource.get('currency') == 'usd': usd_value = UsdCourse.objects.first().value @@ -129,7 +131,7 @@ class PartyListSerializer(serializers.ModelSerializer): 'id': obj.mediator.id, 'full_name': obj.mediator.full_name } - + def get_counterparty(self, obj): counterparties = obj.orders.values("counterparty__id", "counterparty__name").distinct() counterparties = [ @@ -155,7 +157,7 @@ class DeletedPartyCreateSerializer(serializers.Serializer): comment=validated_data.get('comment'), party=validated_data.get('party') ) - + class DeletedPartyListSerializer(serializers.ModelSerializer): party_number = serializers.IntegerField(source='party.number') @@ -167,13 +169,13 @@ class DeletedPartyListSerializer(serializers.ModelSerializer): fields = [ 'id', 'deleted_date', 'party_number', 'party_total_price', 'mediator' ] - + def get_mediator(self, obj): return { 'id': obj.party.mediator.id, 'name': obj.party.mediator.full_name } - + class PartyOrderUpdateSerializer(serializers.Serializer): order_id = serializers.UUIDField() @@ -214,7 +216,7 @@ class PartyOrderUpdateSerializer(serializers.Serializer): counterparty = Counterparty.objects.filter(id=data['counterparty_id']).first() if not counterparty: raise serializers.ValidationError(f"Counterparty not found on {order.id}") - + data['order'] = order data['product'] = product data['unity'] = unity @@ -234,12 +236,12 @@ class PartyUpdateSerializer(serializers.ModelSerializer): ] extra_kwargs = { 'mediator': {'required': False}, - 'delivery_date': {'required': False}, + 'delivery_date': {'required': False}, 'payment_date': {'required':False}, 'comment': {'required': False}, 'audit': {'required': False}, 'audit_comment': {'required': False}, - 'discount': {'required': False}, + 'discount': {'required': False}, 'discount_currency': {'required': False}, } @@ -251,7 +253,7 @@ class PartyUpdateSerializer(serializers.ModelSerializer): instance.delivery_date = validated_data.get('delivery_date', instance.delivery_date) instance.payment_date = validated_data.get('payment_date', instance.payment_date) instance.save() - + for order_data in orders_data: order = order_data['order'] order.product = order_data['product'] @@ -266,22 +268,22 @@ class PartyUpdateSerializer(serializers.ModelSerializer): order.project_folder = order_data['project_folder'] if 'project' in order_data: order.project = order_data['project'] - + update_orders.append(order) Order.objects.bulk_update( update_orders, fields=[ - 'product', - 'unity', - 'wherehouse', - 'counterparty', - 'quantity', - 'unit_amount', + 'product', + 'unity', + 'wherehouse', + 'counterparty', + 'quantity', + 'unit_amount', 'currency', - 'total_price', - 'project_folder', + 'total_price', + 'project_folder', 'project' ] ) - return instance \ No newline at end of file + return instance diff --git a/core/apps/orders/tasks/order.py b/core/apps/orders/tasks/order.py index d12f2d6..5ea581f 100644 --- a/core/apps/orders/tasks/order.py +++ b/core/apps/orders/tasks/order.py @@ -6,9 +6,9 @@ from core.apps.wherehouse.models.inventory import Inventory @shared_task def create_inventory(wherehouse, quantity, product, unity, price): Inventory.objects.create( - wherehouse__id=wherehouse, - quantity=quantity, - product__id=product, - unity__id=unity, - price=price + wherehouse_id=wherehouse, + quantity=quantity, + product_id=product, + unity_id=unity, + price=price ) diff --git a/core/apps/wherehouse/serializers/inventory.py b/core/apps/wherehouse/serializers/inventory.py index c7f03af..5009915 100644 --- a/core/apps/wherehouse/serializers/inventory.py +++ b/core/apps/wherehouse/serializers/inventory.py @@ -3,9 +3,9 @@ from rest_framework import serializers from core.apps.wherehouse.models.inventory import Inventory -class WhereHouseInventoryListSerializer(serializers.ModelSerializer): +class InventoryListSerializer(serializers.ModelSerializer): class Meta: model = Inventory fields = [ - 'id', 'quantity', 'product' - ] \ No newline at end of file + 'id', 'quantity', 'product', 'price', 'unity' + ] diff --git a/core/apps/wherehouse/serializers/wherehouse.py b/core/apps/wherehouse/serializers/wherehouse.py index 7905ab7..22da8b2 100644 --- a/core/apps/wherehouse/serializers/wherehouse.py +++ b/core/apps/wherehouse/serializers/wherehouse.py @@ -3,7 +3,7 @@ from django.db import transaction from rest_framework import serializers from core.apps.wherehouse.models.wherehouse import WhereHouse -from core.apps.wherehouse.serializers.inventory import WhereHouseInventoryListSerializer +from core.apps.wherehouse.serializers.inventory import InventoryListSerializer from core.apps.company.serializers.branch import BranchListSerializer from core.apps.company.models import Branch @@ -39,7 +39,7 @@ class WhereHouseCreateSerializer(serializers.Serializer): raise serializers.ValidationError("Branch not found") data['branch'] = branch return data - + def create(self, validated_data): with transaction.atomic(): return WhereHouse.objects.create( @@ -55,10 +55,10 @@ class WhereHouseUpdateSerializer(serializers.ModelSerializer): fields = [ 'name', 'address', 'branch' ] - + def update(self, instance, validated_data): instance.name = validated_data.get('name', instance.name) instance.address = validated_data.get('address', instance.address) instance.branch = validated_data.get('branch', instance.branch) instance.save() - return instance \ No newline at end of file + return instance diff --git a/core/apps/wherehouse/urls.py b/core/apps/wherehouse/urls.py index 34b4feb..ecb1582 100644 --- a/core/apps/wherehouse/urls.py +++ b/core/apps/wherehouse/urls.py @@ -1,6 +1,7 @@ from django.urls import path, include from core.apps.wherehouse.views import wherehouse as wherehouse_views +from core.apps.wherehouse.views import inventory as inventory_views urlpatterns = [ @@ -13,4 +14,9 @@ urlpatterns = [ path('/update/', wherehouse_views.WhereHouseUpdateApiView.as_view()), ] )), -] \ No newline at end of file + path('inventory/', include( + [ + path('/list/', inventory_views.InventoryListApiView.as_view()), + ] + )), +] diff --git a/core/apps/wherehouse/views/inventory.py b/core/apps/wherehouse/views/inventory.py new file mode 100644 index 0000000..7320b67 --- /dev/null +++ b/core/apps/wherehouse/views/inventory.py @@ -0,0 +1,25 @@ +from django.shortcuts import get_object_or_404 + +from rest_framework import generics, views +from rest_framework.response import Response + +from core.apps.wherehouse.serializers import inventory as serializers +from core.apps.wherehouse.models import WhereHouse, Inventory +from core.apps.accounts.permissions.permissions import HasRolePermission + + +class InventoryListApiView(generics.GenericAPIView): + serializer_class = serializers.InventoryListSerializer + queryset = Inventory.objects.all() + permissions_class = [HasRolePermission] + required_permissions = ['wherehouse'] + + def get(self, request, wherehouse_id): + wherehouse = get_object_or_404(WhereHouse, id=wherehouse_id) + inventories = Inventory.objects.filter(wherehouse=wherehouse) + page = self.paginate_queryset(inventories) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(inventories, many=True) + return Response(serializer.data, status=200) diff --git a/docker-compose.yaml b/docker-compose.yaml index e35f6b3..55e3df9 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -50,8 +50,6 @@ services: networks: - uyqur image: redis - ports: - - "6380:6379" celery: build: @@ -64,4 +62,7 @@ services: - redis - web networks: - - uyqur \ No newline at end of file + - uyqur + environment: + - CELERY_BROKER_URL=redis://redis:6379/0 + - CELERY_RESULT_BACKEND=redis://redis:6379/0 \ No newline at end of file diff --git a/docker/Dockerfile.web b/docker/Dockerfile.web index 7d6e714..bad8b32 100644 --- a/docker/Dockerfile.web +++ b/docker/Dockerfile.web @@ -1,13 +1,26 @@ -FROM python:3.13-alpine - -ENV PYTHONPYCACHEPREFIX=/dev/null - -RUN apk update && apk add git gettext +FROM python:3.12 WORKDIR /code -COPY requirements.txt /code/requirements.txt +RUN apt-get update && \ + apt-get install -y \ + gdal-bin \ + libgdal-dev \ + python3-gdal \ + libgeos-dev \ + libproj-dev \ + g++ \ + make \ + wget \ + libfontconfig \ + libxrender1 \ + libjpeg-dev \ + xfonts-base && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* -RUN --mount=type=cache,target=/root/.cache/pip pip install -r requirements.txt -CMD ["sh", "./entrypoint.sh"] \ No newline at end of file +COPY ./ /code +RUN --mount=type=cache,target=/root/.cache/pip python3 -m pip install -r requirements.txt + +CMD ["sh", "./resources/scripts/entrypoint.sh"] \ No newline at end of file