add new apis

This commit is contained in:
behruz-dev
2025-08-11 12:14:44 +05:00
parent c1405bbc8a
commit 66aab361ef
12 changed files with 591 additions and 6 deletions

View File

@@ -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),
),
]

View File

@@ -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'),
),
]

View File

@@ -29,7 +29,8 @@ class EstimateWork(BaseModel):
estimate = models.ForeignKey(
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):
return f"{self.number}.{self.name}"
@@ -42,12 +43,12 @@ class EstimateWork(BaseModel):
class EstimateProduct(BaseModel):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='estimate_products')
quantity = models.PositiveIntegerField(default=1)
price = models.PositiveBigIntegerField()
unity = models.ForeignKey(
Unity, on_delete=models.SET_NULL, null=True, related_name='estimate_products'
)
price = models.PositiveBigIntegerField(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):
return f'{self.product} - {self.price}'

View 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

View 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

View File

@@ -2,14 +2,17 @@ from django.db import transaction
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):
estimate_works = EstimateWorkListSerializer(many=True)
class Meta:
model = ProjectEstimate
fields = [
'id', 'number', 'name'
'id', 'number', 'name', 'estimate_works'
]

View File

@@ -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 builder as builder_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 = [
path('project/', include(
@@ -38,5 +40,19 @@ urlpatterns = [
path('<uuid:id>/update/', estimate_views.ProjectEstimateUpdateApiView.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()),
]
))
]

View 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)

View 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)

View File

@@ -10,7 +10,7 @@ from core.apps.projects.serializers import project_estimate as serializers
class ProjectEstimateListApiView(generics.ListAPIView):
serializer_class = serializers.ProjectEstimateListSerializer
queryset = ProjectEstimate.objects.all()
queryset = ProjectEstimate.objects.prefetch_related('estimate_works')
permission_classes = [HasRolePermission]
required_permissions = ['project']
@@ -54,4 +54,3 @@ class ProjectEstimateDeleteApiView(generics.GenericAPIView):
estimte = get_object_or_404(ProjectEstimate, id=id)
estimte.delete()
return Response({"success": True, "message": "deleted"}, status=204)