change: change offer model, and add new api

This commit is contained in:
behruz-dev
2025-09-24 15:34:42 +05:00
parent bab2825361
commit 0acc0a920a
8 changed files with 83 additions and 8 deletions

View File

@@ -5,6 +5,6 @@ from core.apps.orders.models import Offer
@admin.register(Offer)
class OfferAdmin(admin.ModelAdmin):
list_display = ['id', 'number', 'order']
list_display = ['id', 'number', 'order', 'status']
search_fields = ['phone', 'number', 'price']

View File

@@ -7,6 +7,6 @@ class OrderFilter(django_filters.FilterSet):
class Meta:
model = Order
fields = [
'wherehouse', 'project', 'project_folder', 'date'
'wherehouse', 'project', 'project_folder', 'date',
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-09-24 14:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0023_alter_party_orders'),
]
operations = [
migrations.AddField(
model_name='offer',
name='status',
field=models.CharField(choices=[('CANCELLED', 'rad etildi'), ('PENDING', 'kutilmoqda'), ('CONFIRMED', 'tasdiqlandi')], default='PENDING', max_length=20),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-09-24 14:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('orders', '0024_offer_status'),
]
operations = [
migrations.AlterField(
model_name='offer',
name='status',
field=models.CharField(blank=True, choices=[('CANCELLED', 'rad etildi'), ('PENDING', 'kutilmoqda'), ('CONFIRMED', 'tasdiqlandi')], default='PENDING', max_length=20, null=True),
),
]

View File

@@ -10,15 +10,23 @@ class Offer(BaseModel):
('UZS', 'uzs'),
('USD', 'usd')
)
STATUS = (
('CANCELLED', 'rad etildi'),
('PENDING', 'kutilmoqda'),
('CONFIRMED', 'tasdiqlandi'),
)
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='offers')
counterparty = models.ForeignKey(Counterparty, on_delete=models.CASCADE, related_name='offers', null=True)
counterparty = models.ForeignKey(
Counterparty, on_delete=models.CASCADE, related_name='offers', null=True
)
price = models.PositiveBigIntegerField()
price_type = models.CharField(choices=PRICE_TYPE, default='uzs')
phone = models.CharField(max_length=15, null=True, blank=True)
comment = models.TextField(null=True, blank=True)
qqs = models.BooleanField(default=False, null=True, blank=True)
number = models.PositiveIntegerField(default=1)
status = models.CharField(max_length=20, choices=STATUS, default='PENDING', null=True, blank=True)
def __str__(self):
return str(self.number)

View File

@@ -95,7 +95,8 @@ class OffersSerializer(serializers.ModelSerializer):
class Meta:
model = Offer
fields = [
'id', 'number', 'price', 'price_type', 'phone', 'comment', 'qqs', 'counterparty', 'created_at'
'id', 'number', 'price', 'price_type', 'phone', 'comment', 'qqs', 'counterparty',
'status', 'created_at'
]
def get_counterparty(self, obj):
@@ -106,7 +107,7 @@ class OffersSerializer(serializers.ModelSerializer):
class OrderListForOfferSerializer(serializers.ModelSerializer):
offers = OffersSerializer(many=True)
offers = serializers.SerializerMethodField(method_name='get_offers')
product = serializers.SerializerMethodField(method_name='get_product')
unity = serializers.SerializerMethodField(method_name='get_unity')
@@ -128,3 +129,11 @@ class OrderListForOfferSerializer(serializers.ModelSerializer):
'id': obj.unity.id,
'value': obj.unity.value
}
def get_offers(self, obj):
status = self.context.get('status')
if status:
offers = obj.offers.filter(status=status)
return OffersSerializer(offers, many=True).data
else:
return OffersSerializer(obj.offers, many=True).data

View File

@@ -25,6 +25,7 @@ urlpatterns = [
path('<uuid:id>/delete/', offer_views.OfferDeleteApiView.as_view()),
path('<uuid:id>/update/', offer_views.OfferUpdateApiView.as_view()),
path('bulk-delete/', offer_views.DeleteMultipleOfferApiView.as_view()),
path('<uuid:id>/change-status/', offer_views.ChangeOfferStatusApiView.as_view()),
]
)),
path('party/', include(

View File

@@ -40,10 +40,14 @@ class OfferListApiView(generics.GenericAPIView):
filterset_class = OrderFilter
def get(self, request):
offer_status = request.query_params.get('status', None)
orders = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(orders)
if page is not None:
serializer = self.serializer_class(page, many=True)
if offer_status:
serializer = self.serializer_class(page, many=True, context={'status': offer_status})
else:
serializer = self.serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.serializer_class(offers, many=True)
return Response(serializer.data, status=200)
@@ -101,3 +105,20 @@ class DeleteMultipleOfferApiView(views.APIView):
deleted_count, _ = Offer.objects.filter(id__in=ids).delete()
return Response({"deleted": deleted_count}, status=200)
class ChangeOfferStatusApiView(views.APIView):
permission_classes = [HasRolePermission]
def post(self, request, id):
offer = get_object_or_404(Offer, id=id)
status = request.data.get('status')
if not status:
return Response({'success': False, 'message': 'status field is required'}, status=400)
offer.status = status
offer.save()
return Response(
{'success': True, 'message': 'status updated'},
status=200
)