add new apis
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
CORS_ALLOWED_ORIGINS = [
|
CORS_ALLOWED_ORIGINS = [
|
||||||
"http://localhost:8081",
|
"http://localhost:8081",
|
||||||
"http://127.0.0.1:8081",
|
"http://127.0.0.1:8081",
|
||||||
|
'https://uyqur.vercel.app'
|
||||||
]
|
]
|
||||||
|
|
||||||
CSRF_TRUSTED_ORIGINS = [
|
CSRF_TRUSTED_ORIGINS = [
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Generated by Django 5.2.4 on 2025-08-09 15:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('projects', '0013_projectestimate_estimateproduct_estimatework'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='estimatework',
|
||||||
|
name='total_price',
|
||||||
|
field=models.PositiveBigIntegerField(default=0),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='project',
|
||||||
|
name='benifit_plan',
|
||||||
|
field=models.PositiveBigIntegerField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 5.2.4 on 2025-08-11 11:35
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('projects', '0014_estimatework_total_price_alter_project_benifit_plan'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='estimateproduct',
|
||||||
|
name='estimate_work',
|
||||||
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='estimate_products', to='projects.estimatework'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -29,7 +29,8 @@ class EstimateWork(BaseModel):
|
|||||||
estimate = models.ForeignKey(
|
estimate = models.ForeignKey(
|
||||||
ProjectEstimate, on_delete=models.CASCADE, related_name='estimate_works'
|
ProjectEstimate, on_delete=models.CASCADE, related_name='estimate_works'
|
||||||
)
|
)
|
||||||
date = models.DateField(null=True, blank=True)
|
date = models.DateField(null=True, blank=True)
|
||||||
|
total_price = models.PositiveBigIntegerField(default=0)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.number}.{self.name}"
|
return f"{self.number}.{self.name}"
|
||||||
@@ -42,12 +43,12 @@ class EstimateWork(BaseModel):
|
|||||||
class EstimateProduct(BaseModel):
|
class EstimateProduct(BaseModel):
|
||||||
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='estimate_products')
|
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='estimate_products')
|
||||||
quantity = models.PositiveIntegerField(default=1)
|
quantity = models.PositiveIntegerField(default=1)
|
||||||
price = models.PositiveBigIntegerField()
|
|
||||||
unity = models.ForeignKey(
|
unity = models.ForeignKey(
|
||||||
Unity, on_delete=models.SET_NULL, null=True, related_name='estimate_products'
|
Unity, on_delete=models.SET_NULL, null=True, related_name='estimate_products'
|
||||||
)
|
)
|
||||||
price = models.PositiveBigIntegerField(null=True, blank=True)
|
price = models.PositiveBigIntegerField(null=True, blank=True)
|
||||||
date = models.DateField(null=True, blank=True)
|
date = models.DateField(null=True, blank=True)
|
||||||
|
estimate_work = models.ForeignKey(EstimateWork, on_delete=models.CASCADE, related_name='estimate_products', null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.product} - {self.price}'
|
return f'{self.product} - {self.price}'
|
||||||
|
|||||||
76
core/apps/projects/serializers/estimate_product.py
Normal file
76
core/apps/projects/serializers/estimate_product.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from core.apps.projects.models.project_estimate import EstimateProduct, EstimateWork
|
||||||
|
from core.apps.products.models import Product, Unity
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateProductListSerializer(serializers.ModelSerializer):
|
||||||
|
product = serializers.SerializerMethodField(method_name='get_product')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = EstimateProduct
|
||||||
|
fields = [
|
||||||
|
'id', 'product', 'quantity', 'price', 'unity', 'price', 'date'
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_product(self, obj):
|
||||||
|
return {
|
||||||
|
'id': obj.product.id,
|
||||||
|
'name': obj.product.name,
|
||||||
|
'type': obj.product.type
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateProductCreateSerializer(serializers.Serializer):
|
||||||
|
product_id = serializers.UUIDField()
|
||||||
|
quantity = serializers.IntegerField()
|
||||||
|
price = serializers.IntegerField()
|
||||||
|
unity_id = serializers.UUIDField(required=False)
|
||||||
|
date = serializers.DateField()
|
||||||
|
estimate_work_id = serializers.UUIDField()
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
product = Product.objects.filter(id=data['product_id']).first()
|
||||||
|
if not product:
|
||||||
|
raise serializers.ValidationError("Product not found")
|
||||||
|
estimate_work = EstimateWork.objects.filter(id=data['estimate_work_id']).first()
|
||||||
|
if not estimate_work:
|
||||||
|
raise serializers.ValidationError("EstimateWork not found")
|
||||||
|
if data.get('unity_id'):
|
||||||
|
unity = Unity.objects.filter(id=data['unity_id']).first()
|
||||||
|
if not unity:
|
||||||
|
raise serializers.ValidationError("Unity not found")
|
||||||
|
data['unity'] = unity
|
||||||
|
data['product'] = product
|
||||||
|
data['estimate_work'] = estimate_work
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
with transaction.atomic():
|
||||||
|
return EstimateProduct.objects.create(
|
||||||
|
product=validated_data.get('product'),
|
||||||
|
quantity=validated_data.get('quantity'),
|
||||||
|
price=validated_data.get('price'),
|
||||||
|
unity=validated_data.get('unity'),
|
||||||
|
date=validated_data.get('date'),
|
||||||
|
estimate_work=validated_data.get('estimate_work'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateProductUpdateSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = EstimateProduct
|
||||||
|
fields = [
|
||||||
|
'product', 'quantity', 'price', 'unity', 'date'
|
||||||
|
]
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
instance.product = validated_data.get('product', instance.product)
|
||||||
|
instance.quantity = validated_data.get('quantity', instance.quantity)
|
||||||
|
instance.price = validated_data.get('price', instance.price)
|
||||||
|
instance.unity = validated_data.get('unity', instance.unity)
|
||||||
|
instance.date = validated_data.get('date', instance.date)
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
81
core/apps/projects/serializers/estimate_work.py
Normal file
81
core/apps/projects/serializers/estimate_work.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from core.apps.projects.models.project_estimate import EstimateWork, ProjectEstimate
|
||||||
|
from core.apps.products.models.unity import Unity
|
||||||
|
from core.apps.projects.serializers.estimate_product import EstimateProductListSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateWorkListSerializer(serializers.ModelSerializer):
|
||||||
|
unity = serializers.SerializerMethodField(method_name='get_unity')
|
||||||
|
estimate_products = EstimateProductListSerializer(many=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = EstimateWork
|
||||||
|
fields = [
|
||||||
|
'id', 'number', 'name', 'quantity', 'unity', 'price', 'date', 'total_price', 'estimate_products'
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_unity(self, obj):
|
||||||
|
return {
|
||||||
|
"id": obj.unity.id,
|
||||||
|
'value': obj.unity.value
|
||||||
|
} if obj.unity else None
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateWorkCreateSerializer(serializers.Serializer):
|
||||||
|
number = serializers.IntegerField()
|
||||||
|
name = serializers.CharField()
|
||||||
|
quantity = serializers.IntegerField()
|
||||||
|
unity_id = serializers.UUIDField(required=False)
|
||||||
|
price = serializers.IntegerField(required=False)
|
||||||
|
date = serializers.DateField(required=False)
|
||||||
|
total_price = serializers.IntegerField(required=False)
|
||||||
|
estimate_id = serializers.UUIDField()
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
unity_id = data.get('unity_id')
|
||||||
|
if unity_id:
|
||||||
|
unity = Unity.objects.filter(id=unity_id).first()
|
||||||
|
if not unity:
|
||||||
|
raise serializers.ValidationError("Unity not found")
|
||||||
|
data['unity'] = unity
|
||||||
|
estimate = ProjectEstimate.objects.filter(id=data['estimate_id']).first()
|
||||||
|
if not estimate:
|
||||||
|
raise serializers.ValidationError("estimate not found")
|
||||||
|
data['estimate'] = estimate
|
||||||
|
return data
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
with transaction.atomic():
|
||||||
|
estimate_work = EstimateWork.objects.create(
|
||||||
|
number=validated_data.get('number'),
|
||||||
|
name=validated_data.get('name'),
|
||||||
|
quantity=validated_data.get('quantity'),
|
||||||
|
unity=validated_data.get('unity'),
|
||||||
|
price=validated_data.get('price'),
|
||||||
|
date=validated_data.get('date'),
|
||||||
|
total_price=validated_data.get('total_price'),
|
||||||
|
estimate=validated_data.get('estimate')
|
||||||
|
)
|
||||||
|
return estimate_work
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateWorkUpdateSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = EstimateWork
|
||||||
|
fields = [
|
||||||
|
'name', 'quantity', 'price', 'unity', 'date', 'total_price',
|
||||||
|
]
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
instance.name = validated_data.get('name', instance.name)
|
||||||
|
instance.quantity = validated_data.get('quantity', instance.quantity)
|
||||||
|
instance.price = validated_data.get('price', instance.price)
|
||||||
|
instance.unity = validated_data.get('unity', instance.unity)
|
||||||
|
instance.date = validated_data.get('date', instance.date)
|
||||||
|
instance.total_price = validated_data.get('total_price', instance.total_price)
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
@@ -2,14 +2,17 @@ from django.db import transaction
|
|||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from core.apps.projects.models.project_estimate import EstimateProduct, EstimateWork, ProjectEstimate
|
from core.apps.projects.models.project_estimate import ProjectEstimate
|
||||||
|
from core.apps.projects.serializers.estimate_work import EstimateWorkListSerializer
|
||||||
|
|
||||||
|
|
||||||
class ProjectEstimateListSerializer(serializers.ModelSerializer):
|
class ProjectEstimateListSerializer(serializers.ModelSerializer):
|
||||||
|
estimate_works = EstimateWorkListSerializer(many=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProjectEstimate
|
model = ProjectEstimate
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'number', 'name'
|
'id', 'number', 'name', 'estimate_works'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ from django.urls import path, include
|
|||||||
from core.apps.projects.views import project as project_views
|
from core.apps.projects.views import project as project_views
|
||||||
from core.apps.projects.views import builder as builder_views
|
from core.apps.projects.views import builder as builder_views
|
||||||
from core.apps.projects.views import project_estimate as estimate_views
|
from core.apps.projects.views import project_estimate as estimate_views
|
||||||
|
from core.apps.projects.views import estimate_work as estimate_work_views
|
||||||
|
from core.apps.projects.views import estimate_product as estimate_product_views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('project/', include(
|
path('project/', include(
|
||||||
@@ -38,5 +40,19 @@ urlpatterns = [
|
|||||||
path('<uuid:id>/update/', estimate_views.ProjectEstimateUpdateApiView.as_view()),
|
path('<uuid:id>/update/', estimate_views.ProjectEstimateUpdateApiView.as_view()),
|
||||||
path('<uuid:id>/delete/', estimate_views.ProjectEstimateDeleteApiView.as_view()),
|
path('<uuid:id>/delete/', estimate_views.ProjectEstimateDeleteApiView.as_view()),
|
||||||
]
|
]
|
||||||
|
)),
|
||||||
|
path('estimate_work/', include(
|
||||||
|
[
|
||||||
|
path('create/', estimate_work_views.EstimateWorkCreateApiView.as_view()),
|
||||||
|
path('<uuid:id>/update/', estimate_work_views.EstimateWorkUpdateApiView.as_view()),
|
||||||
|
path('<uuid:id>/delete/', estimate_work_views.EstimateWorkDeleteApiView.as_view()),
|
||||||
|
]
|
||||||
|
)),
|
||||||
|
path('estimate_product/', include(
|
||||||
|
[
|
||||||
|
path('create/', estimate_product_views.EstimateProductCreateApiView.as_view()),
|
||||||
|
path('<uuid:id>/update/', estimate_product_views.EstimateProductUpdateApiView.as_view()),
|
||||||
|
path('<uuid:id>/delete/', estimate_product_views.EstimateProductDeleteApiView.as_view()),
|
||||||
|
]
|
||||||
))
|
))
|
||||||
]
|
]
|
||||||
47
core/apps/projects/views/estimate_product.py
Normal file
47
core/apps/projects/views/estimate_product.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
|
from rest_framework import generics, views
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from core.apps.projects.serializers import estimate_product as serializers
|
||||||
|
from core.apps.projects.models.project_estimate import EstimateProduct
|
||||||
|
from core.apps.accounts.permissions.permissions import HasRolePermission
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateProductCreateApiView(generics.GenericAPIView):
|
||||||
|
permission_classes = [HasRolePermission]
|
||||||
|
required_permissions = ['project']
|
||||||
|
serializer_class = serializers.EstimateProductCreateSerializer
|
||||||
|
queryset = EstimateProduct.objects.all()
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
serializer = self.serializer_class(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response({"success": True, 'message': 'created'}, status=201)
|
||||||
|
return Response({'success': False, 'message': serializer.errors}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateProductUpdateApiView(generics.GenericAPIView):
|
||||||
|
serializer_class = serializers.EstimateProductUpdateSerializer
|
||||||
|
queryset = EstimateProduct.objects.all()
|
||||||
|
permission_classes = [HasRolePermission]
|
||||||
|
required_permissions = ['project']
|
||||||
|
|
||||||
|
def patch(self, request, id):
|
||||||
|
estimate_product = get_object_or_404(EstimateProduct, id=id)
|
||||||
|
serializer = self.serializer_class(data=request.data, instance=estimate_product, partial=True)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response({"success": True, "message": 'updated'}, status=200)
|
||||||
|
return Response({"success": False, 'message': serializer.errors}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateProductDeleteApiView(views.APIView):
|
||||||
|
permission_classes = [HasRolePermission]
|
||||||
|
required_permissions = ['project']
|
||||||
|
|
||||||
|
def delete(self, request, id):
|
||||||
|
estimate_product = get_object_or_404(EstimateProduct, id=id)
|
||||||
|
estimate_product.delete()
|
||||||
|
return Response({"success": True}, status=204)
|
||||||
47
core/apps/projects/views/estimate_work.py
Normal file
47
core/apps/projects/views/estimate_work.py
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
|
from rest_framework import generics, views
|
||||||
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from core.apps.accounts.permissions.permissions import HasRolePermission
|
||||||
|
from core.apps.projects.models.project_estimate import EstimateWork
|
||||||
|
from core.apps.projects.serializers import estimate_work as serializers
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateWorkCreateApiView(generics.GenericAPIView):
|
||||||
|
serializer_class = serializers.EstimateWorkCreateSerializer
|
||||||
|
queryset = EstimateWork.objects.all()
|
||||||
|
permission_classes = [HasRolePermission]
|
||||||
|
required_permissions = ['project', 'project_folder']
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
serializer = self.serializer_class(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response({'success': True, 'message': 'created!'}, status=201)
|
||||||
|
return Response({'success': False, 'message': serializer.errors}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateWorkUpdateApiView(generics.GenericAPIView):
|
||||||
|
serializer_class = serializers.EstimateWorkUpdateSerializer
|
||||||
|
queryset = EstimateWork.objects.all()
|
||||||
|
permission_classes = [HasRolePermission]
|
||||||
|
required_permissions = ['project', 'project_folder']
|
||||||
|
|
||||||
|
def patch(self, request, id):
|
||||||
|
estimate_work = get_object_or_404(EstimateWork, id=id)
|
||||||
|
serializer = self.serializer_class(data=request.data, instance=estimate_work)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response({"success": True, "message": "Updated"}, status=200)
|
||||||
|
return Response({'success': False, 'message': serializer.errors}, status=400)
|
||||||
|
|
||||||
|
|
||||||
|
class EstimateWorkDeleteApiView(views.APIView):
|
||||||
|
permission_classes = [HasRolePermission]
|
||||||
|
required_permissions = ['project']
|
||||||
|
|
||||||
|
def delete(self, request, id):
|
||||||
|
work = get_object_or_404(EstimateWork, id=id)
|
||||||
|
work.delete()
|
||||||
|
return Response({"success": True}, status=204)
|
||||||
@@ -10,7 +10,7 @@ from core.apps.projects.serializers import project_estimate as serializers
|
|||||||
|
|
||||||
class ProjectEstimateListApiView(generics.ListAPIView):
|
class ProjectEstimateListApiView(generics.ListAPIView):
|
||||||
serializer_class = serializers.ProjectEstimateListSerializer
|
serializer_class = serializers.ProjectEstimateListSerializer
|
||||||
queryset = ProjectEstimate.objects.all()
|
queryset = ProjectEstimate.objects.prefetch_related('estimate_works')
|
||||||
permission_classes = [HasRolePermission]
|
permission_classes = [HasRolePermission]
|
||||||
required_permissions = ['project']
|
required_permissions = ['project']
|
||||||
|
|
||||||
@@ -54,4 +54,3 @@ class ProjectEstimateDeleteApiView(generics.GenericAPIView):
|
|||||||
estimte = get_object_or_404(ProjectEstimate, id=id)
|
estimte = get_object_or_404(ProjectEstimate, id=id)
|
||||||
estimte.delete()
|
estimte.delete()
|
||||||
return Response({"success": True, "message": "deleted"}, status=204)
|
return Response({"success": True, "message": "deleted"}, status=204)
|
||||||
|
|
||||||
272
resources/logs/django.log.2025-08-09
Normal file
272
resources/logs/django.log.2025-08-09
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
WARNING 2025-08-09 11:54:16,155 log Forbidden: /api/v1/projects/project/list/
|
||||||
|
WARNING 2025-08-09 11:54:24,194 log Not Found: /
|
||||||
|
WARNING 2025-08-09 11:54:24,296 log Not Found: /favicon.ico
|
||||||
|
ERROR 2025-08-09 12:13:13,318 log Internal Server Error: /api/v1/projects/project/8b40e979-0274-48d3-92f0-007bd2e11d71/
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 437, in get_attribute
|
||||||
|
return get_attribute(instance, self.source_attrs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 104, in get_attribute
|
||||||
|
instance = getattr(instance, attr)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
AttributeError: 'ManyRelatedManager' object has no attribute 'address'
|
||||||
|
|
||||||
|
During handling of the above exception, another exception occurred:
|
||||||
|
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 42, in inner
|
||||||
|
response = await get_response(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
|
||||||
|
response = await wrapped_callback(
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 439, in __call__
|
||||||
|
ret = await asyncio.shield(exec_coro)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 59, in run
|
||||||
|
result = self.fn(*self.args, **self.kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 493, in thread_handler
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
|
||||||
|
return self.dispatch(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
|
||||||
|
response = self.handle_exception(exc)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
|
||||||
|
self.raise_uncaught_exception(exc)
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
|
||||||
|
raise exc
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
|
||||||
|
response = handler(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/generics.py", line 212, in get
|
||||||
|
return self.retrieve(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/mixins.py", line 56, in retrieve
|
||||||
|
return Response(serializer.data)
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 573, in data
|
||||||
|
ret = super().data
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 251, in data
|
||||||
|
self._data = self.to_representation(self.instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 540, in to_representation
|
||||||
|
ret[field.field_name] = field.to_representation(attribute)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 527, in to_representation
|
||||||
|
attribute = field.get_attribute(instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 470, in get_attribute
|
||||||
|
raise type(exc)(msg)
|
||||||
|
AttributeError: Got AttributeError when attempting to get a value for field `address` on serializer `WhereHouseListSerializer`.
|
||||||
|
The serializer field might be named incorrectly and not match any attribute or key on the `ManyRelatedManager` instance.
|
||||||
|
Original exception text was: 'ManyRelatedManager' object has no attribute 'address'.
|
||||||
|
ERROR 2025-08-09 12:13:14,831 log Internal Server Error: /api/v1/projects/project/8b40e979-0274-48d3-92f0-007bd2e11d71/
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 437, in get_attribute
|
||||||
|
return get_attribute(instance, self.source_attrs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 104, in get_attribute
|
||||||
|
instance = getattr(instance, attr)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
AttributeError: 'ManyRelatedManager' object has no attribute 'address'
|
||||||
|
|
||||||
|
During handling of the above exception, another exception occurred:
|
||||||
|
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 42, in inner
|
||||||
|
response = await get_response(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
|
||||||
|
response = await wrapped_callback(
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 439, in __call__
|
||||||
|
ret = await asyncio.shield(exec_coro)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 59, in run
|
||||||
|
result = self.fn(*self.args, **self.kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 493, in thread_handler
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
|
||||||
|
return self.dispatch(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
|
||||||
|
response = self.handle_exception(exc)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
|
||||||
|
self.raise_uncaught_exception(exc)
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
|
||||||
|
raise exc
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
|
||||||
|
response = handler(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/generics.py", line 212, in get
|
||||||
|
return self.retrieve(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/mixins.py", line 56, in retrieve
|
||||||
|
return Response(serializer.data)
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 573, in data
|
||||||
|
ret = super().data
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 251, in data
|
||||||
|
self._data = self.to_representation(self.instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 540, in to_representation
|
||||||
|
ret[field.field_name] = field.to_representation(attribute)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 527, in to_representation
|
||||||
|
attribute = field.get_attribute(instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 470, in get_attribute
|
||||||
|
raise type(exc)(msg)
|
||||||
|
AttributeError: Got AttributeError when attempting to get a value for field `address` on serializer `WhereHouseListSerializer`.
|
||||||
|
The serializer field might be named incorrectly and not match any attribute or key on the `ManyRelatedManager` instance.
|
||||||
|
Original exception text was: 'ManyRelatedManager' object has no attribute 'address'.
|
||||||
|
ERROR 2025-08-09 15:14:16,166 log Internal Server Error: /swagger/
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 42, in inner
|
||||||
|
response = await get_response(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 235, in _get_response_async
|
||||||
|
callback, callback_args, callback_kwargs = self.resolve_request(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 313, in resolve_request
|
||||||
|
resolver_match = resolver.resolve(request.path_info)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/urls/resolvers.py", line 666, in resolve
|
||||||
|
for pattern in self.url_patterns:
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/utils/functional.py", line 47, in __get__
|
||||||
|
res = instance.__dict__[self.name] = self.func(instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/urls/resolvers.py", line 718, in url_patterns
|
||||||
|
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/utils/functional.py", line 47, in __get__
|
||||||
|
res = instance.__dict__[self.name] = self.func(instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/urls/resolvers.py", line 711, in urlconf_module
|
||||||
|
return import_module(self.urlconf_name)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module
|
||||||
|
return _bootstrap._gcd_import(name[level:], package, level)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
|
||||||
|
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
|
||||||
|
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
|
||||||
|
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
|
||||||
|
File "<frozen importlib._bootstrap_external>", line 999, in exec_module
|
||||||
|
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
|
||||||
|
File "/code/config/urls.py", line 33, in <module>
|
||||||
|
path('projects/', include('core.apps.projects.urls')),
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/urls/conf.py", line 39, in include
|
||||||
|
urlconf_module = import_module(urlconf_module)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module
|
||||||
|
return _bootstrap._gcd_import(name[level:], package, level)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
|
||||||
|
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
|
||||||
|
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
|
||||||
|
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
|
||||||
|
File "<frozen importlib._bootstrap_external>", line 995, in exec_module
|
||||||
|
File "<frozen importlib._bootstrap_external>", line 1133, in get_code
|
||||||
|
File "<frozen importlib._bootstrap_external>", line 1063, in source_to_code
|
||||||
|
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
|
||||||
|
File "/code/core/apps/projects/urls.py", line 39
|
||||||
|
path('<uuid:id>/delete/', estimate_views.)
|
||||||
|
^
|
||||||
|
SyntaxError: invalid syntax
|
||||||
|
WARNING 2025-08-09 15:14:16,990 log Not Found: /favicon.ico
|
||||||
|
ERROR 2025-08-09 15:35:41,275 log Internal Server Error: /api/v1/projects/project_estimate/list/
|
||||||
|
Traceback (most recent call last):
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 42, in inner
|
||||||
|
response = await get_response(request)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 489, in thread_handler
|
||||||
|
raise exc_info[1]
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
|
||||||
|
response = await wrapped_callback(
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 439, in __call__
|
||||||
|
ret = await asyncio.shield(exec_coro)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 59, in run
|
||||||
|
result = self.fn(*self.args, **self.kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/asgiref/sync.py", line 493, in thread_handler
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
|
||||||
|
return view_func(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
|
||||||
|
return self.dispatch(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 515, in dispatch
|
||||||
|
response = self.handle_exception(exc)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 475, in handle_exception
|
||||||
|
self.raise_uncaught_exception(exc)
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
|
||||||
|
raise exc
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 512, in dispatch
|
||||||
|
response = handler(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/generics.py", line 203, in get
|
||||||
|
return self.list(request, *args, **kwargs)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/mixins.py", line 43, in list
|
||||||
|
return self.get_paginated_response(serializer.data)
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 797, in data
|
||||||
|
ret = super().data
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 251, in data
|
||||||
|
self._data = self.to_representation(self.instance)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 716, in to_representation
|
||||||
|
self.child.to_representation(item) for item in iterable
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 540, in to_representation
|
||||||
|
ret[field.field_name] = field.to_representation(attribute)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 716, in to_representation
|
||||||
|
self.child.to_representation(item) for item in iterable
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/serializers.py", line 540, in to_representation
|
||||||
|
ret[field.field_name] = field.to_representation(attribute)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
File "/usr/local/lib/python3.12/site-packages/rest_framework/fields.py", line 1870, in to_representation
|
||||||
|
return method(value)
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
File "/code/core/apps/projects/serializers/project_estimate.py", line 20, in get_unity
|
||||||
|
'name': obj.unity.name
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
AttributeError: 'Unity' object has no attribute 'name'
|
||||||
Reference in New Issue
Block a user