diff --git a/.gitignore b/.gitignore index 5270754..698b1a2 100644 --- a/.gitignore +++ b/.gitignore @@ -266,4 +266,6 @@ poetry.toml # LSP config files pyrightconfig.json -# End of https://www.toptal.com/developers/gitignore/api/python,django \ No newline at end of file +# End of https://www.toptal.com/developers/gitignore/api/python,django + +.zed/ diff --git a/config/settings/base.py b/config/settings/base.py index 432b1e4..31d0280 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -161,4 +161,4 @@ AUTH_USER_MODEL = "accounts.User" SECURE_PROXY_SSL_HEADER = ( "HTTP_X_FORWARDED_PROTO", env.str("SWAGGER_PROTOCOL", "https"), -) \ No newline at end of file +) diff --git a/core/apps/accounts/admin/permission.py b/core/apps/accounts/admin/permission.py index ca582e2..e503e4c 100644 --- a/core/apps/accounts/admin/permission.py +++ b/core/apps/accounts/admin/permission.py @@ -1,19 +1,24 @@ -from django.contrib import admin +from django.contrib import admin -from core.apps.accounts.models.permission import Permission, PermissionToTab, PermissionToAction +from core.apps.accounts.models.permission import ( + Permission, + PermissionToTab, + PermissionToAction, +) @admin.register(Permission) class PermissionAdmin(admin.ModelAdmin): - list_display = ['name', 'code'] - filter_horizontal = ['permission_tab'] + list_display = ["name", "code"] + filter_horizontal = ["permission_tab"] + @admin.register(PermissionToTab) class PermissionToTabAdmin(admin.ModelAdmin): - list_display = ['name', 'code'] - filter_horizontal = ['permission_to_actions'] + list_display = ["name", "code"] + filter_horizontal = ["permission_to_actions"] @admin.register(PermissionToAction) class PermissionToActionAdmin(admin.ModelAdmin): - list_display = ['name', 'code'] \ No newline at end of file + list_display = ["name", "code"] diff --git a/core/apps/orders/migrations/0035_order_completion_percentage_order_received_count_and_more.py b/core/apps/orders/migrations/0035_order_completion_percentage_order_received_count_and_more.py new file mode 100644 index 0000000..f49faa9 --- /dev/null +++ b/core/apps/orders/migrations/0035_order_completion_percentage_order_received_count_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.2.4 on 2025-11-10 15:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('orders', '0034_alter_offer_price_alter_order_amount_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='completion_percentage', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='order', + name='received_count', + field=models.PositiveBigIntegerField(default=0), + ), + migrations.AddField( + model_name='order', + name='received_date', + field=models.DateField(blank=True, null=True), + ), + ] diff --git a/core/apps/orders/models/order.py b/core/apps/orders/models/order.py index 8e7972a..de01fc1 100644 --- a/core/apps/orders/models/order.py +++ b/core/apps/orders/models/order.py @@ -49,6 +49,10 @@ class Order(BaseModel): amount = models.DecimalField(max_digits=15, decimal_places=2, default=0.00) qqs = models.PositiveBigIntegerField(null=True, blank=True) + received_count = models.PositiveBigIntegerField(default=0) + received_date = models.DateField(null=True, blank=True) + completion_percentage = models.FloatField(default=0) + def __str__(self): return f"{self.product} {self.unity} quantity order" diff --git a/core/apps/orders/serializers/order.py b/core/apps/orders/serializers/order.py index 52208c7..13b63bf 100644 --- a/core/apps/orders/serializers/order.py +++ b/core/apps/orders/serializers/order.py @@ -112,7 +112,7 @@ class OrderListSerializer(serializers.ModelSerializer): fields = [ 'id', 'product', 'unity', 'quantity', 'project', 'project_folder', 'wherehouse', 'date', 'status', 'employee', 'counterparty', 'unit_amount', 'currency', - 'total_price', 'qqs_price', 'amount', 'qqs' + 'total_price', 'qqs_price', 'amount', 'qqs', 'received_count', 'received_date', 'completion_percentage' ] def get_employee(self, obj): diff --git a/core/apps/orders/serializers/party.py b/core/apps/orders/serializers/party.py index 61f3b08..11ebafe 100644 --- a/core/apps/orders/serializers/party.py +++ b/core/apps/orders/serializers/party.py @@ -517,3 +517,13 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): payment_type.save() return expence + + +class ReceivePartySerializer(serializers.Serializer): + order_id = serializers.UUIDField() + product_quantity = serializers.IntegerField() + product_receive_date = serializers.DateField() + + +class ReceiveMultipleOrderSerializer(serializers.Serializer): + product = ReceivePartySerializer(many=True) \ No newline at end of file diff --git a/core/apps/orders/tasks/order.py b/core/apps/orders/tasks/order.py index e3e585f..321e91f 100644 --- a/core/apps/orders/tasks/order.py +++ b/core/apps/orders/tasks/order.py @@ -5,7 +5,9 @@ from core.apps.wherehouse.models.inventory import Inventory @shared_task -def create_inventory(wherehouse, quantity, product, unity, price, project_folder, project, unity_price): +def create_inventory( + wherehouse, quantity, product, unity, price, project_folder, project, unity_price +): inventory, created = Inventory.objects.get_or_create( product_id=product, wherehouse_id=wherehouse, @@ -15,7 +17,7 @@ def create_inventory(wherehouse, quantity, product, unity, price, project_folder price=price, project_folder_id=project_folder, project_id=project, - unit_price=unity_price + unit_price=unity_price, ) ) if not created: diff --git a/core/apps/orders/views/party.py b/core/apps/orders/views/party.py index 52c609b..fda4587 100644 --- a/core/apps/orders/views/party.py +++ b/core/apps/orders/views/party.py @@ -141,27 +141,40 @@ class OrderDeleteToPartyApiView(generics.GenericAPIView): class PartyChangeStatusToIsMadeApiView(generics.GenericAPIView): - serializer_class = None + serializer_class = serializers.ReceiveMultipleOrderSerializer queryset = Party.objects.all() permission_classes = [HasRolePermission] pagination_class = None - def get(self, request, party_id): + def post(self, request, party_id): + serializer = self.serializer_class(data=request.data) + if not serializer.is_valid(raise_exception=True): + return Response({"success": False, "message": serializer.errors}, status=400) party = get_object_or_404(Party, id=party_id) party.status = 'PARTY_IS_MADE' party.save() - for order in party.orders.all(): - create_inventory.delay( - order.wherehouse.id, - order.quantity, - order.product.id, - order.unity.id, - order.unit_amount * order.quantity, - order.project_folder.id if order.project_folder else None, - order.project.id if order.project else None, - order.unit_amount, - ) - return Response( + data = serializer.validated_data + for item in data['product']: + order_id = item['order_id'] + product_quantity = item['product_quantity'] + product_receive_date = item['product_receive_date'] + for order in party.orders.all(): + if order.id == order_id: + completion_percentage = (product_quantity / order.quantity) * 100 + create_inventory.delay( + order.wherehouse.id, + order.quantity, + order.product.id, + order.unity.id, + order.unit_amount * order.quantity, + order.project_folder.id if order.project_folder else None, + order.project.id if order.project else None, + order.unit_amount, + ) + order.received_count += product_quantity + order.received_date = product_receive_date + order.comletion_percentage = completion_percentage + return Response( {'success': True, 'message': 'party updated'}, status=200 )