From 3f2b86be576035ae061c98285d429567907d2c8f Mon Sep 17 00:00:00 2001 From: behruz-dev Date: Sat, 1 Nov 2025 08:45:57 +0500 Subject: [PATCH] finance: import income and expence commands added --- .../commands/import_income_expence.py | 122 ++++++++++++++++++ core/apps/finance/serializers/expence.py | 37 +----- core/apps/finance/serializers/income.py | 37 +----- core/apps/orders/serializers/party.py | 18 --- 4 files changed, 135 insertions(+), 79 deletions(-) create mode 100644 core/apps/finance/management/commands/import_income_expence.py diff --git a/core/apps/finance/management/commands/import_income_expence.py b/core/apps/finance/management/commands/import_income_expence.py new file mode 100644 index 0000000..09c73c8 --- /dev/null +++ b/core/apps/finance/management/commands/import_income_expence.py @@ -0,0 +1,122 @@ +import requests +from datetime import datetime + +from django.core.management import BaseCommand + +from core.apps.finance.models import ( + Income, + Expence, + TypeIncome, + ExpenceType, + CashTransaction, + PaymentType +) +from core.apps.projects.models import ProjectFolder +from core.apps.accounts.models import User +from core.apps.wherehouse.models import WhereHouse +from core.apps.counterparty.models import Counterparty +from core.apps.orders.models import Party + + +headers = { + "Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2JhY2tlbmQuYXBwLnV5cXVyLnV6L21haW4vYXV0aC9sb2dpbiIsImlhdCI6MTc2MTkyMDM2MSwiZXhwIjoxNzYyMDA2NzYxLCJuYmYiOjE3NjE5MjAzNjEsImp0aSI6Inhqak81azJLc2pSaEJJOGUiLCJzdWIiOiIxMDQiLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.ZcREfvT21qpd9eK_-zBumKBtaKKJ-l9QoudSLZ3IpP4" +} + + +def get_data(page): + url = f"https://backend.app.uyqur.uz/main/payment/view?size=500&page={page}" + + response = requests.get(url, headers=headers) + if response.status_code == 200: + return response.json() + return response.json() + + +def create_expense(data): + statuses = { + "passive": "PENDING", + "active": "CONFIRMED", + "cancel": "CANCELLED" + } + user = User.objects.filter(full_name=data['creator']['full_name']).first() + cash_transaction = CashTransaction.objects.filter(name=data['cash']['name']).first() + expence_type = None + if data.get('financila'): + expence_type = ExpenceType.objects.filter(name=data['financial']['name']).first() + project_folder = None + if data.get('project'): + project_folder = ProjectFolder.objects.filter(name=data['project']['name']).first() + payment_type, created = PaymentType.objects.get_or_create(name=data['payment_type']['name']) + counterparty = None + if data.get('company_person'): + counterparty = Counterparty.objects.filter(name=data['company_person']['name']).first() + party = None + if data.get('order_ids'): + party_number = data.get('order_ids')[0] + party = Party.objects.filter(number=party_number).first() + Expence.objects.get_or_create( + user=user, + cash_transaction=cash_transaction, + expence_type=expence_type, + price=data['amount'], + currency=data['currency']['symbol'].lower(), + defaults={ + "payment_type": payment_type, + "project_folder": project_folder, + "counterparty": counterparty, + "exchange_rate": data['currency_amount'], + "date": datetime.strptime(data['date'], "%d.%m.%Y").date(), + "comment": data['description'], + "status": statuses.get(data['status']), + "party": party, + } + ) + +def create_income(data): + user = User.objects.filter(full_name=data['creator']['full_name']).first() + cash_transaction = CashTransaction.objects.filter(name=data['cash']['name']).first() + payment_type, created = PaymentType.objects.get_or_create(name=data['payment_type']['name']) + income_type = None + if data.get('financiel'): + income_type = TypeIncome.objects.filter(name=data['financial']['name']).first() + project_folder = None + if data.get('project'): + project_folder = ProjectFolder.objects.filter(name=data['project']['name']).first() + counterparty = None + if data.get('company_person'): + counterparty = Counterparty.objects.filter(name=data['company_person']['name']).first() + Income.objects.get_or_create( + user=user, + cash_transaction=cash_transaction, + type_income=income_type, + price=data['amount'], + currency=data['currency']['symbol'].lower(), + defaults={ + "payment_type": payment_type, + "project_folder": project_folder, + "counterparty": counterparty, + "exchange_rate": data['currency_amount'], + "date": datetime.strptime(data['date'], "%d.%m.%Y").date(), + "comment": data['description'], + } + ) + + +class Command(BaseCommand): + def handle(self, *args, **options): + total_data = 13756 + page = 1 + size = 500 + count = 0 + for page in range(round(total_data / size)): + data = get_data(page) + print(page) + for item in data['data']['data']: + match item['type']: + case "expense": + create_expense(item) + case "income": + create_income(item) + count += 1 + page += 1 + self.stdout.write(self.style.SUCCESS(f"{count} ta Income va Expenselar qo'shildi")) diff --git a/core/apps/finance/serializers/expence.py b/core/apps/finance/serializers/expence.py index a12a35a..4649ea0 100644 --- a/core/apps/finance/serializers/expence.py +++ b/core/apps/finance/serializers/expence.py @@ -15,7 +15,6 @@ class ExpenceCreateSerializer(serializers.ModelSerializer): ] def validate(self, data): - """Balanslari tekshirish""" cash_transaction = data.get('cash_transaction') payment_type = data.get('payment_type') price = data.get('price') @@ -24,7 +23,6 @@ class ExpenceCreateSerializer(serializers.ModelSerializer): final_price = price - # Payment type balansi tekshiruvi if currency == 'uzs' and payment_type.total_uzs < final_price: raise serializers.ValidationError(f"Yetarli UZS balansi yo'q. Mavjud: {payment_type.total_uzs}") elif currency == 'usd' and payment_type.total_usd < final_price: @@ -60,56 +58,43 @@ class ExpenceCreateSerializer(serializers.ModelSerializer): user = self.context.get('user') if currency == 'uzs': - # Cash transaction balansini yangilash cash_transaction.expence_balance_uzs += expence.price cash_transaction.total_balance_uzs = cash_transaction.income_balance_uzs - cash_transaction.expence_balance_uzs - # Payment type balansini kamayitish payment_type.total_uzs -= expence.price - # Kontrapartiya hisobini yangilash if expence.counterparty: if expence.counterparty.kredit_uzs > 0: - # Kredit bo'lsa, uni qisqartirish expence.counterparty.kredit_uzs -= expence.price expence.counterparty.total_kredit -= expence.price - # Debit oshirish expence.counterparty.debit_uzs += expence.price expence.counterparty.total_debit += expence.price else: - # Kredit yo'q bo'lsa, to'g'ridan-to'g'ri debit oshirish expence.counterparty.debit_uzs += expence.price expence.counterparty.total_debit += expence.price expence.counterparty.save() elif currency == 'usd': - # Cash transaction balansini yangilash cash_transaction.expence_balance_usd += expence.price cash_transaction.total_balance_usd = cash_transaction.income_balance_usd - cash_transaction.expence_balance_usd - # Payment type balansini kamayitish payment_type.total_usd -= expence.price - # Kontrapartiya hisobini yangilash if expence.counterparty: if expence.counterparty.kredit_usd > 0: - # Kredit bo'lsa, uni qisqartirish - expence.counterparty.kredit_usd -= expence.price # ✅ TUZATILDI + expence.counterparty.kredit_usd -= expence.price expence.counterparty.total_kredit -= expence.price - # Debit oshirish - expence.counterparty.debit_usd += expence.price # ✅ TUZATILDI + expence.counterparty.debit_usd += expence.price expence.counterparty.total_debit += expence.price else: - # Kredit yo'q bo'lsa, to'g'ridan-to'g'ri debit oshirish - expence.counterparty.debit_usd += expence.price # ✅ TUZATILDI + expence.counterparty.debit_usd += expence.price expence.counterparty.total_debit += expence.price expence.counterparty.save() - # Bildirishnoma yuborish body = f"""{user.full_name} {expence.price} {expence.currency.upper()}... \n screen: /monitoring""" data = { "screen": "/monitoring", @@ -200,7 +185,6 @@ class ExpenceUpdateSerializer(serializers.ModelSerializer): } def validate_price(self, value): - """Narxi manfiy bo'lmasligi tekshiruvi""" if value and value < 0: raise serializers.ValidationError("Narxi manfiy bo'lishi mumkin emas") return value @@ -213,7 +197,6 @@ class ExpenceUpdateSerializer(serializers.ModelSerializer): new_counterparty = validated_data.get('counterparty', instance.counterparty) currency = instance.currency.lower() - # Asosiy ma'lumotlarni yangilash instance.project_folder = validated_data.get('project_folder', instance.project_folder) instance.project = validated_data.get('project', instance.project) instance.price = new_price @@ -224,38 +207,31 @@ class ExpenceUpdateSerializer(serializers.ModelSerializer): instance.audit = validated_data.get('audit', instance.audit) instance.file = validated_data.get('file', instance.file) - # Agar narxi o'zgarsa, balanslarni yangilash if validated_data.get('price') and old_price != new_price: - price_difference = new_price - old_price # ✅ To'g'ri farq + price_difference = new_price - old_price cash_transaction = instance.cash_transaction payment_type = instance.payment_type if currency == 'uzs': - # Cash transaction balansini yangilash cash_transaction.expence_balance_uzs += price_difference cash_transaction.total_balance_uzs = ( cash_transaction.income_balance_uzs - cash_transaction.expence_balance_uzs ) - # Payment type balansini yangilash - payment_type.total_uzs -= price_difference # ✅ Narx oshsa, balans kamayadi + payment_type.total_uzs -= price_difference elif currency == 'usd': - # Cash transaction balansini yangilash cash_transaction.expence_balance_usd += price_difference cash_transaction.total_balance_usd = ( cash_transaction.income_balance_usd - cash_transaction.expence_balance_usd ) - # Payment type balansini yangilash - payment_type.total_usd -= price_difference # ✅ Narx oshsa, balans kamayadi + payment_type.total_usd -= price_difference cash_transaction.save() payment_type.save() - # Agar kontrapartiya o'zgarsa, uning hisobini yangilash if new_counterparty != old_counterparty: - # Eski kontrapartyani qaytarish if old_counterparty: if currency == 'uzs': if old_counterparty.debit_uzs > 0: @@ -274,7 +250,6 @@ class ExpenceUpdateSerializer(serializers.ModelSerializer): old_counterparty.save() - # Yangi kontrapartyani yangilash if new_counterparty: if currency == 'uzs': if new_counterparty.kredit_uzs > 0: diff --git a/core/apps/finance/serializers/income.py b/core/apps/finance/serializers/income.py index 0af0174..8a6f286 100644 --- a/core/apps/finance/serializers/income.py +++ b/core/apps/finance/serializers/income.py @@ -98,7 +98,6 @@ class IncomeCreateSerializer(serializers.ModelSerializer): ] def validate(self, data): - """Validasiya qilish""" price = data.get('price') exchange_rate = data.get('exchange_rate') @@ -112,7 +111,6 @@ class IncomeCreateSerializer(serializers.ModelSerializer): def create(self, validated_data): with transaction.atomic(): - # Exchange rate va final price hisoblash exchange_rate = validated_data.get("exchange_rate") or 1 final_price = validated_data.get("price") @@ -138,57 +136,45 @@ class IncomeCreateSerializer(serializers.ModelSerializer): currency = validated_data.get("currency", "uzs").lower() if currency == "uzs": - # Cash transaction balansini yangilash cash_transaction.income_balance_uzs += income.price cash_transaction.total_balance_uzs = ( cash_transaction.income_balance_uzs - cash_transaction.expence_balance_uzs ) - # Payment type balansini yangilash payment_type.total_uzs += income.price - # Kontrapartiya hisobini yangilash if income.counterparty: if income.counterparty.debit_uzs > 0: - # Debit bo'lsa, uni qisqartirish income.counterparty.debit_uzs -= income.price income.counterparty.total_debit -= income.price - # Kredit oshirish - income.counterparty.kredit_uzs += income.price # ✅ TUZATILDI + income.counterparty.kredit_uzs += income.price income.counterparty.total_kredit += income.price else: - # Debit yo'q bo'lsa, to'g'ridan-to'g'ri kredit oshirish income.counterparty.kredit_uzs += income.price income.counterparty.total_kredit += income.price income.counterparty.save() elif currency == "usd": - # Cash transaction balansini yangilash cash_transaction.income_balance_usd += income.price cash_transaction.total_balance_usd = ( cash_transaction.income_balance_usd - cash_transaction.expence_balance_usd ) - # Payment type balansini yangilash payment_type.total_usd += income.price - # Kontrapartiya hisobini yangilash if income.counterparty: if income.counterparty.debit_usd > 0: - # Debit bo'lsa, uni qisqartirish - income.counterparty.debit_usd -= income.price # ✅ TUZATILDI + income.counterparty.debit_usd -= income.price income.counterparty.total_debit -= income.price - # Kredit oshirish - income.counterparty.kredit_usd += income.price # ✅ TUZATILDI + income.counterparty.kredit_usd += income.price income.counterparty.total_kredit += income.price else: - # Debit yo'q bo'lsa, to'g'ridan-to'g'ri kredit oshirish - income.counterparty.kredit_usd += income.price # ✅ TUZATILDI + income.counterparty.kredit_usd += income.price income.counterparty.total_kredit += income.price income.counterparty.save() @@ -234,7 +220,6 @@ class IncomeUpdateSerializer(serializers.ModelSerializer): new_counterparty = validated_data.get("counterparty", instance.counterparty) currency = instance.currency.lower() - # Asosiy ma'lumotlarni yangilash instance.project_folder = validated_data.get( "project_folder", instance.project_folder ) @@ -247,40 +232,33 @@ class IncomeUpdateSerializer(serializers.ModelSerializer): instance.audit = validated_data.get("audit", instance.audit) instance.file = validated_data.get("file", instance.file) - # Agar narxi o'zgarsa, balanslarni yangilash if validated_data.get("price") and old_price != new_price: - price_difference = new_price - old_price # ✅ To'g'ri farq + price_difference = new_price - old_price cash_transaction = instance.cash_transaction payment_type = instance.payment_type if currency == "uzs": - # Cash transaction balansini yangilash cash_transaction.income_balance_uzs += price_difference cash_transaction.total_balance_uzs = ( cash_transaction.income_balance_uzs - cash_transaction.expence_balance_uzs ) - # Payment type balansini yangilash - payment_type.total_uzs += price_difference # ✅ Narx oshsa, balans oshadi + payment_type.total_uzs += price_difference elif currency == "usd": - # Cash transaction balansini yangilash cash_transaction.income_balance_usd += price_difference cash_transaction.total_balance_usd = ( cash_transaction.income_balance_usd - cash_transaction.expence_balance_usd ) - # Payment type balansini yangilash - payment_type.total_usd += price_difference # ✅ Narx oshsa, balans oshadi + payment_type.total_usd += price_difference cash_transaction.save() payment_type.save() - # Agar kontrapartiya o'zgarsa, uning hisobini yangilash if new_counterparty != old_counterparty: - # Eski kontrapartyani qaytarish if old_counterparty: if currency == "uzs": if old_counterparty.kredit_uzs > 0: @@ -299,7 +277,6 @@ class IncomeUpdateSerializer(serializers.ModelSerializer): old_counterparty.save() - # Yangi kontrapartyani yangilash if new_counterparty: if currency == "uzs": if new_counterparty.debit_uzs > 0: diff --git a/core/apps/orders/serializers/party.py b/core/apps/orders/serializers/party.py index b497cde..7a39eae 100644 --- a/core/apps/orders/serializers/party.py +++ b/core/apps/orders/serializers/party.py @@ -382,7 +382,6 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): ] def validate(self, data): - """Validasiya qilish""" price = data.get('price') exchange_rate = data.get('exchange_rate') party = data.get('party') @@ -397,7 +396,6 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): if not party: raise serializers.ValidationError("Party talab qilinadi") - # USD kursi tekshiruvi try: usd_course = UsdCourse.objects.first() if not usd_course or not usd_course.value: @@ -439,24 +437,20 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): party = expence.party if currency == "uzs": - # Cash transaction balansini yangilash cash_transaction.expence_balance_uzs += expence.price cash_transaction.total_balance_uzs = ( cash_transaction.income_balance_uzs - cash_transaction.expence_balance_uzs ) - # Payment type balansini yangilash if payment_type.total_uzs > expence.price: payment_type.total_uzs -= expence.price - # Kontrapartiya hisobini yangilash if expence.counterparty: if expence.counterparty.kredit_uzs > 0: expence.counterparty.kredit_uzs -= expence.price expence.counterparty.total_kredit -= expence.price - # ✅ TUZATILDI: Debit to'g'ridan-to'g'ri oshadi expence.counterparty.debit_uzs += expence.price expence.counterparty.total_debit += expence.price else: @@ -465,15 +459,12 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): expence.counterparty.save() - # Party hisobini yangilash if party: if party.currency == "uzs": - # ✅ Birjani to'g'ri hisoblash party.party_amount.payment_amount -= expence.price party.party_amount.paid_amount += expence.price party.party_amount.save() elif party.currency == 'usd': - # ✅ USD kursi bilan to'g'ri konvertatsiya converted_price = round(expence.price / usd_value) party.party_amount.payment_amount -= converted_price party.party_amount.paid_amount += converted_price @@ -482,25 +473,20 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): party.save() elif currency == "usd": - # Cash transaction balansini yangilash cash_transaction.expence_balance_usd += expence.price cash_transaction.total_balance_usd = ( cash_transaction.income_balance_usd - cash_transaction.expence_balance_usd ) - # Payment type balansini yangilash if payment_type.total_usd > expence.price: payment_type.total_usd -= expence.price - # Kontrapartiya hisobini yangilash if expence.counterparty: if expence.counterparty.kredit_usd > 0: - # ✅ TUZATILDI: expence.price ishlatish expence.counterparty.kredit_usd -= expence.price expence.counterparty.total_kredit -= expence.price - # ✅ TUZATILDI: Debit to'g'ridan-to'g'ri oshadi expence.counterparty.debit_usd += expence.price expence.counterparty.total_debit += expence.price else: @@ -509,15 +495,12 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): expence.counterparty.save() - # Party hisobini yangilash if party: if party.currency == "usd": - # ✅ TUZATILDI: expence.price ishlatish party.party_amount.payment_amount -= expence.price party.party_amount.paid_amount += expence.price party.party_amount.save() elif party.currency == "uzs": - # ✅ TUZATILDI: expence.price bilan konvertatsiya converted_price = expence.price * usd_value party.party_amount.payment_amount -= converted_price party.party_amount.paid_amount += converted_price @@ -525,7 +508,6 @@ class PartyExpenceCreateSerializer(serializers.ModelSerializer): party.save() - # Barcha o'zgarishlari saqlash cash_transaction.save() payment_type.save()