add: add expence api

This commit is contained in:
behruz-dev
2025-09-09 15:07:58 +05:00
parent ee9f06701a
commit e98e40a3c7
8 changed files with 222 additions and 2 deletions

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-09-09 14:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('finance', '0011_paymenttype_total_usd_paymenttype_total_uzs_and_more'),
]
operations = [
migrations.AddField(
model_name='expence',
name='file',
field=models.FileField(blank=True, null=True, unique='finance/expence/files/', upload_to=''),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-09-09 15:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('finance', '0012_expence_file'),
]
operations = [
migrations.AlterField(
model_name='expence',
name='file',
field=models.FileField(blank=True, null=True, upload_to='finance/expence/files/'),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-09-09 15:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('finance', '0013_alter_expence_file'),
]
operations = [
migrations.AlterField(
model_name='expence',
name='exchange_rate',
field=models.PositiveBigIntegerField(blank=True, default=0, null=True),
),
]

View File

@@ -22,13 +22,14 @@ class Expence(BaseModel):
)
price = models.PositiveBigIntegerField()
exchange_rate = models.PositiveBigIntegerField(default=0)
exchange_rate = models.PositiveBigIntegerField(default=0, null=True, blank=True)
currency = models.CharField(
max_length=3, choices=[('usd','usd'), ('uzs', 'uzs')]
)
date = models.DateField(null=True, blank=True)
comment = models.TextField(null=True, blank=True)
audit = models.CharField(max_length=200, null=True, blank=True)
file = models.FileField(null=True, blank=True, upload_to='finance/expence/files/')
def __str__(self):
return f'{self.cash_transaction} kassa uchun chiqim {self.price}'

View File

@@ -23,7 +23,9 @@ class CashTransactionListSerializer(serializers.ModelSerializer):
class Meta:
model = CashTransaction
fields = [
'id', 'name', 'payment_type', 'employees', 'status'
'id', 'name', 'payment_type', 'employees', 'status', 'total_balance_usd',
'income_balance_usd', 'expence_balance_usd', 'total_balance_uzs',
'income_balance_uzs', 'expence_balance_uzs'
]

View File

@@ -0,0 +1,104 @@
from django.db import transaction
from rest_framework import serializers
from core.apps.finance.models import Expence
class ExpenceCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Expence
fields = [
'cash_transaction', 'payment_type', 'project_folder', 'project', 'expence_type',
'counterparty', 'price', 'exchange_rate', 'currency', 'date', 'comment', 'audit', 'file'
]
def create(self, validated_data):
with transaction.atomic():
expence = Expence.objects.create(
cash_transaction=validated_data.get('cash_transaction'),
payment_type=validated_data.get('payment_type'),
project_folder=validated_data.get('project_folder'),
project=validated_data.get('project'),
expence_type=validated_data.get('expence_type'),
counterparty=validated_data.get('counterparty'),
price=validated_data.get('price') * validated_data.get('exchange_rate') if validated_data.get('exchange_rate') else validated_data.get('price'),
exchange_rate=validated_data.get('exchange_rate'),
currency=validated_data.get('currency'),
date=validated_data.get('date'),
comment=validated_data.get('comment'),
audit=validated_data.get('audit'),
file=validated_data.get('file'),
)
cash_transaction = expence.cash_transaction
payment_type = expence.payment_type
if validated_data.get('currency') == 'uzs':
cash_transaction.expence_balance_uzs += expence.price
cash_transaction.total_balance_uzs = cash_transaction.income_balance_uzs - cash_transaction.expence_balance_uzs
if payment_type.total_uzs > expence.price:
payment_type.total_uzs -= expence.price
elif validated_data.get('currency') == 'usd':
cash_transaction.expence_balance_usd += expence.price
if cash_transaction.income_balance_usd > cash_transaction.expence_balance_usd:
cash_transaction.total_balance_usd = cash_transaction.income_balance_usd - cash_transaction.expence_balance_usd
else:
cash_transaction.total_balance_usd = 0
if payment_type.total_usd > expence.price:
payment_type.total_usd -= expence.price
cash_transaction.save()
payment_type.save()
return expence
class ExpenceListSerializer(serializers.ModelSerializer):
cash_transaction = serializers.SerializerMethodField(method_name='get_cash_transaction')
payment_type = serializers.SerializerMethodField(method_name='get_payment_type')
project_folder = serializers.SerializerMethodField(method_name='get_project_folder')
project = serializers.SerializerMethodField(method_name='get_project')
counterparty = serializers.SerializerMethodField(method_name='get_counterparty')
expence_type = serializers.SerializerMethodField(method_name='get_expence_type')
class Meta:
model = Expence
fields = [
'id', 'cash_transaction', 'payment_type', 'project_folder', 'project', 'expence_type',
'counterparty', 'price', 'exchange_rate', 'currency', 'date', 'comment', 'audit', 'file'
]
def get_cash_transaction(self, obj):
return {
'id': obj.cash_transaction.id,
'name': obj.cash_transaction.name
}
def get_payment_type(self, obj):
return {
'id': obj.payment_type.id,
'name': obj.payment_type.name
}
def get_project_folder(self, obj):
return {
'id': obj.project_folder.id,
'name': obj.project_folder.name
}
def get_project(self, obj):
return {
'id': obj.project.id,
'name': obj.project.name
} if obj.project else None
def get_counterparty(self, obj):
return {
'id': obj.counterparty.id,
'name': obj.counterparty.name
} if obj.counterparty else None
def get_expence_type(self, obj):
return {
'id': obj.expence_type.id,
'name': obj.expence_type.name
} if obj.expence_type else None

View File

@@ -6,6 +6,7 @@ from core.apps.finance.views import payment_type as pt_views
from core.apps.finance.views import type_income as ti_views
from core.apps.finance.views import income as income_views
from core.apps.finance.views import expence_type as ex_views
from core.apps.finance.views import expence as expence_views
urlpatterns = [
@@ -55,4 +56,10 @@ urlpatterns = [
path('<uuid:id>/delete/', ex_views.ExpenceTypeDeleteApiView.as_view()),
]
)),
path('expence/', include(
[
path('list/', expence_views.ExpenceListApiView.as_view()),
path('create/', expence_views.ExpenceCreateApiView.as_view()),
]
))
]

View File

@@ -0,0 +1,52 @@
from rest_framework import generics, views, parsers
from rest_framework.response import Response
from core.apps.accounts.permissions.permissions import HasRolePermission
from core.apps.finance.models import Expence
from core.apps.finance.serializers import expence as serializers
class ExpenceCreateApiView(generics.GenericAPIView):
serializer_class = serializers.ExpenceCreateSerializer
queryset = Expence.objects.select_related(
'cash_transaction', 'payment_type', 'project_folder', 'project',
'counterparty', 'expence_type',
)
permission_classes = [HasRolePermission]
parser_classes = [parsers.FormParser, parsers.MultiPartParser]
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(
{
'success': True,
'message': 'Expence created'
},
status=201
)
return Response(
{
'success': False,
'message': 'Expence create failed',
'error': serializer.errors
},
status=400
)
class ExpenceListApiView(generics.GenericAPIView):
serializer_class = serializers.ExpenceListSerializer
queryset = Expence.objects.select_related(
'cash_transaction', 'payment_type', 'project_folder', 'project',
'counterparty', 'expence_type',
)
permission_classes = [HasRolePermission]
def get(self, request):
page = self.paginate_queryset(self.queryset)
if page is not None:
serializer = self.serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)