From 243d879243f1ce94475d0577487b64643bd2d212 Mon Sep 17 00:00:00 2001 From: Abdulaziz Axmadaliyev Date: Wed, 18 Feb 2026 17:28:30 +0500 Subject: [PATCH] Some changes have been made --- core/apps/accounts/migrations/0001_initial.py | 2 +- core/apps/accounts/migrations/0002_initial.py | 9 +- .../migrations/0003_user_warehouse.py | 20 -- ..._alter_user_region_alter_user_warehouse.py | 25 -- core/apps/management/admin.py | 19 +- core/apps/management/forms/IncomeForm.py | 31 +-- .../management/migrations/0001_initial.py | 70 ++++- .../0002_expensetype_expense_income.py | 46 --- .../0003_load_uzbekistan_regions_districts.py | 125 --------- .../migrations/0004_alter_device_name.py | 18 -- ...ter_toymovement_from_warehouse_and_more.py | 24 -- .../0006_remove_device_warehouse.py | 17 -- ...expense_expense_type_delete_expensetype.py | 21 -- .../0008_alter_expense_expense_type.py | 18 -- .../0009_alter_expense_expense_type.py | 18 -- ...xpense_device_expense_employee_and_more.py | 31 --- .../0011_alter_expense_confirmed_by.py | 21 -- ..._reported_by_income_created_by_and_more.py | 41 --- ...ress_remove_device_monthly_fee_and_more.py | 44 --- .../migrations/0014_alter_income_amount.py | 18 -- .../0015_remove_income_confirmed_by.py | 17 -- ...nt_created_by_rent_is_paid_rent_paid_at.py | 31 --- .../migrations/0017_expense_comment.py | 18 -- .../migrations/0018_income_warehouse.py | 19 -- .../0019_alter_expense_expense_type.py | 18 -- ...e_amount_device_due_date_device_is_paid.py | 28 -- .../apps/management/migrations/0021_report.py | 26 -- .../migrations/0022_alter_district_region.py | 19 -- core/apps/management/models/income.py | 30 +- .../businessman/businessman_dashboard.html | 9 + .../common/create/income_create.html | 45 +-- .../common/lists/device_payment_list.html | 43 ++- .../templates/common/lists/income_list.html | 127 ++++----- .../common/lists/toy_movement_statistics.html | 261 ++++++++++++++++++ .../employee/employee_dashboard.html | 4 +- .../templates/manager/manager_dashboard.html | 4 + core/apps/management/urls.py | 2 +- core/apps/management/views/common/create.py | 14 +- core/apps/management/views/common/list.py | 60 +++- core/apps/shared/migrations/0001_initial.py | 11 +- ...d_at_settingsmodel_description_and_more.py | 46 --- 41 files changed, 566 insertions(+), 884 deletions(-) delete mode 100644 core/apps/accounts/migrations/0003_user_warehouse.py delete mode 100644 core/apps/accounts/migrations/0004_alter_user_region_alter_user_warehouse.py delete mode 100644 core/apps/management/migrations/0002_expensetype_expense_income.py delete mode 100644 core/apps/management/migrations/0003_load_uzbekistan_regions_districts.py delete mode 100644 core/apps/management/migrations/0004_alter_device_name.py delete mode 100644 core/apps/management/migrations/0005_alter_toymovement_from_warehouse_and_more.py delete mode 100644 core/apps/management/migrations/0006_remove_device_warehouse.py delete mode 100644 core/apps/management/migrations/0007_alter_expense_expense_type_delete_expensetype.py delete mode 100644 core/apps/management/migrations/0008_alter_expense_expense_type.py delete mode 100644 core/apps/management/migrations/0009_alter_expense_expense_type.py delete mode 100644 core/apps/management/migrations/0010_expense_device_expense_employee_and_more.py delete mode 100644 core/apps/management/migrations/0011_alter_expense_confirmed_by.py delete mode 100644 core/apps/management/migrations/0012_remove_income_reported_by_income_created_by_and_more.py delete mode 100644 core/apps/management/migrations/0013_rename_name_device_address_remove_device_monthly_fee_and_more.py delete mode 100644 core/apps/management/migrations/0014_alter_income_amount.py delete mode 100644 core/apps/management/migrations/0015_remove_income_confirmed_by.py delete mode 100644 core/apps/management/migrations/0016_rent_created_by_rent_is_paid_rent_paid_at.py delete mode 100644 core/apps/management/migrations/0017_expense_comment.py delete mode 100644 core/apps/management/migrations/0018_income_warehouse.py delete mode 100644 core/apps/management/migrations/0019_alter_expense_expense_type.py delete mode 100644 core/apps/management/migrations/0020_device_amount_device_due_date_device_is_paid.py delete mode 100644 core/apps/management/migrations/0021_report.py delete mode 100644 core/apps/management/migrations/0022_alter_district_region.py create mode 100644 core/apps/management/templates/common/lists/toy_movement_statistics.html delete mode 100644 core/apps/shared/migrations/0002_settingsmodel_created_at_settingsmodel_description_and_more.py diff --git a/core/apps/accounts/migrations/0001_initial.py b/core/apps/accounts/migrations/0001_initial.py index 79b534e..7ac6394 100644 --- a/core/apps/accounts/migrations/0001_initial.py +++ b/core/apps/accounts/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.2 on 2026-02-04 12:15 +# Generated by Django 5.2.7 on 2026-02-18 08:13 import django.utils.timezone from django.db import migrations, models diff --git a/core/apps/accounts/migrations/0002_initial.py b/core/apps/accounts/migrations/0002_initial.py index 73e60b6..c75aeeb 100644 --- a/core/apps/accounts/migrations/0002_initial.py +++ b/core/apps/accounts/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.2 on 2026-02-04 12:15 +# Generated by Django 5.2.7 on 2026-02-18 08:13 import django.db.models.deletion from django.db import migrations, models @@ -18,11 +18,16 @@ class Migration(migrations.Migration): migrations.AddField( model_name='user', name='region', - field=models.ForeignKey(blank=True, help_text='Only for managers', null=True, on_delete=django.db.models.deletion.SET_NULL, to='management.region'), + field=models.ForeignKey(blank=True, help_text='Faqat menejerlar uchun', null=True, on_delete=django.db.models.deletion.SET_NULL, to='management.region'), ), migrations.AddField( model_name='user', name='user_permissions', field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions'), ), + migrations.AddField( + model_name='user', + name='warehouse', + field=models.ForeignKey(blank=True, help_text='Faqat xodimlar uchun', null=True, on_delete=django.db.models.deletion.PROTECT, to='management.warehouse'), + ), ] diff --git a/core/apps/accounts/migrations/0003_user_warehouse.py b/core/apps/accounts/migrations/0003_user_warehouse.py deleted file mode 100644 index 45e012a..0000000 --- a/core/apps/accounts/migrations/0003_user_warehouse.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-06 09:54 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0002_initial'), - ('management', '0013_rename_name_device_address_remove_device_monthly_fee_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='warehouse', - field=models.ForeignKey(blank=True, help_text='Only for employees', null=True, on_delete=django.db.models.deletion.PROTECT, to='management.warehouse'), - ), - ] diff --git a/core/apps/accounts/migrations/0004_alter_user_region_alter_user_warehouse.py b/core/apps/accounts/migrations/0004_alter_user_region_alter_user_warehouse.py deleted file mode 100644 index a429c0a..0000000 --- a/core/apps/accounts/migrations/0004_alter_user_region_alter_user_warehouse.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-17 11:44 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0003_user_warehouse'), - ('management', '0022_alter_district_region'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='region', - field=models.ForeignKey(blank=True, help_text='Faqat menejerlar uchun', null=True, on_delete=django.db.models.deletion.SET_NULL, to='management.region'), - ), - migrations.AlterField( - model_name='user', - name='warehouse', - field=models.ForeignKey(blank=True, help_text='Faqat xodimlar uchun', null=True, on_delete=django.db.models.deletion.PROTECT, to='management.warehouse'), - ), - ] diff --git a/core/apps/management/admin.py b/core/apps/management/admin.py index 02c1723..a61e3fd 100644 --- a/core/apps/management/admin.py +++ b/core/apps/management/admin.py @@ -67,11 +67,20 @@ class ToyMovementAdmin(admin.ModelAdmin): # ------------------------- @admin.register(Income) class IncomeAdmin(admin.ModelAdmin): - list_display = ("device", "amount", "created_by", "created_at") - list_filter = ("device",) - search_fields = ("device__name", "created_by__phone") - autocomplete_fields = ["device", "created_by",] - readonly_fields = ("created_at",) + list_display = ( + "warehouse", + "toys_count", + "price_per_toy", + "total_amount", + "created_at", + ) + + list_filter = ("warehouse", "created_at") + + search_fields = ("warehouse__name",) + + readonly_fields = ("total_amount", "created_at") + # ------------------------- # Expense Admin diff --git a/core/apps/management/forms/IncomeForm.py b/core/apps/management/forms/IncomeForm.py index d481225..b009353 100644 --- a/core/apps/management/forms/IncomeForm.py +++ b/core/apps/management/forms/IncomeForm.py @@ -1,35 +1,18 @@ from django import forms -from ..models import Income, Device, Warehouse +from ..models import Income, Warehouse class IncomeForm(forms.ModelForm): class Meta: model = Income - fields = ["device", "amount", "warehouse"] + fields = ["warehouse", "toys_count", "price_per_toy"] def __init__(self, *args, **kwargs): self.user = kwargs.pop("user", None) super().__init__(*args, **kwargs) - if self.user is not None: - # Filter devices - if self.user.role == "businessman": - self.fields["warehouse"].queryset = Warehouse.objects.all() - elif self.user.role == "manager": - self.fields["warehouse"].queryset = Warehouse.objects.filter(region=self.user.region) - elif self.user.role == "employee": - self.fields["device"].queryset = Device.objects.filter(district__region=self.user.region) - - # Remove amount for employees - if self.user.role == "employee": - self.fields.pop("amount", None) - - def save(self, commit=True): - instance = super().save(commit=False) - if self.user: - instance.created_by = self.user - if getattr(self.user, "role", None) == "employee": - instance.amount = None - if commit: - instance.save() - return instance \ No newline at end of file + # Filter warehouse by manager region + if self.user and self.user.role == "manager": + self.fields["warehouse"].queryset = Warehouse.objects.filter( + region=self.user.region + ) diff --git a/core/apps/management/migrations/0001_initial.py b/core/apps/management/migrations/0001_initial.py index 7f522ff..2b0066e 100644 --- a/core/apps/management/migrations/0001_initial.py +++ b/core/apps/management/migrations/0001_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 6.0.2 on 2026-02-04 12:15 +# Generated by Django 5.2.7 on 2026-02-18 08:13 import django.db.models.deletion +from decimal import Decimal from django.conf import settings from django.db import migrations, models @@ -32,17 +33,58 @@ class Migration(migrations.Migration): name='Device', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=100)), - ('toys_count', models.PositiveIntegerField(default=0)), - ('monthly_fee', models.DecimalField(decimal_places=2, max_digits=10)), + ('address', models.CharField(max_length=100, unique=True)), + ('due_date', models.DateField(blank=True, null=True)), + ('amount', models.IntegerField(blank=True, null=True)), + ('is_paid', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('district', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='management.district')), ], ), + migrations.CreateModel( + name='Expense', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('amount', models.DecimalField(decimal_places=2, max_digits=12)), + ('expense_type', models.CharField(choices=[('salary', 'Maosh'), ('utilities', 'Kommunal to‘lovlar'), ('maintenance', 'Texnik xizmat'), ('food', 'Oziq-ovqat'), ('transport', "Yo'lkira"), ('buy_toys', 'Oʻyinchoqlar sotib olish'), ('other', 'Boshqa')], default='other', max_length=20)), + ('comment', models.TextField(blank=True, null=True)), + ('is_confirmed', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('confirmed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='confirmed_expenses', to=settings.AUTH_USER_MODEL)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='management.device')), + ('employee', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='salaries', to=settings.AUTH_USER_MODEL)), + ], + ), migrations.AddField( model_name='district', name='region', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='districts', to='management.region'), + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='districts', to='management.region'), + ), + migrations.CreateModel( + name='Rent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('address', models.CharField(max_length=100, unique=True)), + ('due_date', models.DateField()), + ('amount', models.IntegerField()), + ('is_paid', models.BooleanField(default=False)), + ('paid_at', models.DateTimeField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='created_rents', to=settings.AUTH_USER_MODEL)), + ('device', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='device_rents', to='management.device')), + ('district', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='district_rents', to='management.district')), + ], + ), + migrations.CreateModel( + name='Report', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('quantity', models.PositiveIntegerField(default=0)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='management.device')), + ], ), migrations.CreateModel( name='Warehouse', @@ -58,19 +100,25 @@ class Migration(migrations.Migration): name='ToyMovement', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('movement_type', models.CharField(choices=[('from_warehouse', 'Warehouse → Device'), ('to_device', 'Device refill'), ('between_warehouses', 'Warehouse → Warehouse')], max_length=30)), + ('movement_type', models.CharField(choices=[('from_warehouse', 'Ombordan → Aparatga'), ('between_warehouses', 'Ombordan → Omborga')], max_length=30)), ('quantity', models.PositiveIntegerField()), ('created_at', models.DateTimeField(auto_now_add=True)), ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='management.device')), - ('from_warehouse', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='outgoing', to='management.warehouse')), + ('from_warehouse', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='outgoing', to='management.warehouse')), ('to_warehouse', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='incoming', to='management.warehouse')), ], ), - migrations.AddField( - model_name='device', - name='warehouse', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='management.warehouse'), + migrations.CreateModel( + name='Income', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('toys_count', models.PositiveIntegerField(default=0)), + ('price_per_toy', models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=12)), + ('total_amount', models.DecimalField(decimal_places=2, default=Decimal('0.00'), editable=False, max_digits=14)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('warehouse', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='warehouse_incomes', to='management.warehouse')), + ], ), migrations.AlterUniqueTogether( name='district', diff --git a/core/apps/management/migrations/0002_expensetype_expense_income.py b/core/apps/management/migrations/0002_expensetype_expense_income.py deleted file mode 100644 index 2f5387c..0000000 --- a/core/apps/management/migrations/0002_expensetype_expense_income.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-04 12:41 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='ExpenseType', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, unique=True)), - ], - ), - migrations.CreateModel( - name='Expense', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('amount', models.DecimalField(decimal_places=2, max_digits=12)), - ('is_confirmed', models.BooleanField(default=False)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('confirmed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='confirmed_expenses', to=settings.AUTH_USER_MODEL)), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), - ('expense_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='expenses', to='management.expensetype')), - ], - ), - migrations.CreateModel( - name='Income', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('amount', models.DecimalField(decimal_places=2, max_digits=12)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('confirmed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='confirmed_income', to=settings.AUTH_USER_MODEL)), - ('device', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='management.device')), - ('reported_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='reported_income', to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/core/apps/management/migrations/0003_load_uzbekistan_regions_districts.py b/core/apps/management/migrations/0003_load_uzbekistan_regions_districts.py deleted file mode 100644 index d493222..0000000 --- a/core/apps/management/migrations/0003_load_uzbekistan_regions_districts.py +++ /dev/null @@ -1,125 +0,0 @@ -from django.db import migrations - - -def load_data(apps, schema_editor): - Region = apps.get_model("management", "Region") - District = apps.get_model("management", "District") - - data = { - "Qoraqalpogʻiston Respublikasi": [ - "Amudaryo tumani", "Beruniy tumani", "Chimboy tumani", - "Ellikqalʼa tumani", "Kegeyli tumani", "Moʻynoq tumani", - "Nukus tumani", "Qanlikoʻl tumani", "Qoʻngʻirot tumani", - "Qoraoʻzak tumani", "Shumanay tumani", "Taxiatosh tumani", - "Taxtakoʻpir tumani", "Toʻrtkoʻl tumani", "Xoʻjayli tumani" - ], - "Andijon viloyati": [ - "Andijon tumani", "Asaka tumani", "Baliqchi tumani", - "Boʻz tumani", "Buloqboshi tumani", "Izboskan tumani", - "Jalaquduq tumani", "Marhamat tumani", "Oltinkoʻl tumani", - "Paxtaobod tumani", "Qoʻrgʻontepa tumani", - "Shahrixon tumani", "Ulugʻnor tumani", "Xoʻjaobod tumani" - ], - "Buxoro viloyati": [ - "Buxoro tumani", "Gʻijduvon tumani", "Jondor tumani", - "Kogon tumani", "Olot tumani", "Peshku tumani", - "Qorakoʻl tumani", "Qorovulbozor tumani", - "Romitan tumani", "Shofirkon tumani", "Vobkent tumani" - ], - "Fargʻona viloyati": [ - "Bagʻdod tumani", "Beshariq tumani", "Dangʻara tumani", - "Fargʻona tumani", "Furqat tumani", "Oltiariq tumani", - "Qoʻshtepa tumani", "Quva tumani", "Rishton tumani", - "Soʻx tumani", "Toshloq tumani", "Uchkoʻprik tumani", - "Yozyovon tumani" - ], - "Jizzax viloyati": [ - "Arnasoy tumani", "Baxmal tumani", "Doʻstlik tumani", - "Forish tumani", "Gʻallaorol tumani", "Mirzachoʻl tumani", - "Paxtakor tumani", "Sharof Rashidov tumani", - "Yangiobod tumani", "Zomin tumani", "Zafarobod tumani" - ], - "Xorazm viloyati": [ - "Bogʻot tumani", "Gurlan tumani", "Hazorasp tumani", - "Qoʻshkoʻpir tumani", "Shovot tumani", - "Urganch tumani", "Xazorasp tumani", "Xiva tumani", - "Yangiariq tumani", "Yangibozor tumani" - ], - "Namangan viloyati": [ - "Chortoq tumani", "Chust tumani", "Kosonsoy tumani", - "Mingbuloq tumani", "Namangan tumani", - "Norin tumani", "Pop tumani", "Toʻraqoʻrgʻon tumani", - "Uchqoʻrgʻon tumani", "Uychi tumani", "Yangiqoʻrgʻon tumani" - ], - "Navoiy viloyati": [ - "Karmana tumani", "Konimex tumani", "Navbahor tumani", - "Nurota tumani", "Qiziltepa tumani", - "Tomdi tumani", "Uchquduq tumani", "Xatirchi tumani" - ], - "Qashqadaryo viloyati": [ - "Chiroqchi tumani", "Dehqonobod tumani", - "Gʻuzor tumani", "Kasbi tumani", "Kitob tumani", - "Koson tumani", "Mirishkor tumani", "Muborak tumani", - "Nishon tumani", "Qamashi tumani", - "Qarshi tumani", "Shahrisabz tumani", - "Yakkabogʻ tumani" - ], - "Samarqand viloyati": [ - "Bulungʻur tumani", "Ishtixon tumani", - "Jomboy tumani", "Kattaqoʻrgʻon tumani", - "Narpay tumani", "Nurobod tumani", - "Oqdaryo tumani", "Paxtachi tumani", - "Pastdargʻom tumani", "Payariq tumani", - "Qoʻshrabot tumani", "Samarqand tumani", - "Toyloq tumani", "Urgut tumani" - ], - "Surxondaryo viloyati": [ - "Angor tumani", "Bandixon tumani", "Boysun tumani", - "Denov tumani", "Jarqoʻrgʻon tumani", - "Muzrabot tumani", "Oltinsoy tumani", - "Qiziriq tumani", "Qumqoʻrgʻon tumani", - "Sariosiyo tumani", "Sherobod tumani", - "Shoʻrchi tumani", "Termiz tumani", "Uzun tumani" - ], - "Sirdaryo viloyati": [ - "Boyovut tumani", "Guliston tumani", - "Mirzaobod tumani", "Oqoltin tumani", - "Sayxunobod tumani", "Sardoba tumani", - "Xovos tumani" - ], - "Toshkent viloyati": [ - "Angren tumani", "Bekobod tumani", - "Boʻka tumani", "Boʻstonliq tumani", - "Chinoz tumani", "Ohangaron tumani", - "Oqqoʻrgʻon tumani", "Parkent tumani", - "Piskent tumani", "Quyi Chirchiq tumani", - "Yangiyoʻl tumani", "Yuqori Chirchiq tumani", - "Zangiota tumani" - ], - "Toshkent shahri": [ - "Bektemir tumani", "Chilonzor tumani", - "Hamza tumani", "Mirobod tumani", - "Mirzo Ulugʻbek tumani", "Olmazor tumani", - "Sergeli tumani", "Shayxontohur tumani", - "Uchtepa tumani", "Yakkasaroy tumani", - "Yashnobod tumani", "Yunusobod tumani" - ], - } - - for region_name, districts in data.items(): - region, _ = Region.objects.get_or_create(name=region_name) - District.objects.bulk_create( - [District(name=d, region=region) for d in districts], - ignore_conflicts=True - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ("management", "0002_expensetype_expense_income"), - ] - - operations = [ - migrations.RunPython(load_data), - ] diff --git a/core/apps/management/migrations/0004_alter_device_name.py b/core/apps/management/migrations/0004_alter_device_name.py deleted file mode 100644 index e8dafd7..0000000 --- a/core/apps/management/migrations/0004_alter_device_name.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 05:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0003_load_uzbekistan_regions_districts'), - ] - - operations = [ - migrations.AlterField( - model_name='device', - name='name', - field=models.CharField(max_length=100, unique=True), - ), - ] diff --git a/core/apps/management/migrations/0005_alter_toymovement_from_warehouse_and_more.py b/core/apps/management/migrations/0005_alter_toymovement_from_warehouse_and_more.py deleted file mode 100644 index 3ea1f16..0000000 --- a/core/apps/management/migrations/0005_alter_toymovement_from_warehouse_and_more.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 06:05 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0004_alter_device_name'), - ] - - operations = [ - migrations.AlterField( - model_name='toymovement', - name='from_warehouse', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='outgoing', to='management.warehouse'), - ), - migrations.AlterField( - model_name='toymovement', - name='movement_type', - field=models.CharField(choices=[('from_warehouse', 'Warehouse → Device'), ('between_warehouses', 'Warehouse → Warehouse')], max_length=30), - ), - ] diff --git a/core/apps/management/migrations/0006_remove_device_warehouse.py b/core/apps/management/migrations/0006_remove_device_warehouse.py deleted file mode 100644 index ea7f9a2..0000000 --- a/core/apps/management/migrations/0006_remove_device_warehouse.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 06:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0005_alter_toymovement_from_warehouse_and_more'), - ] - - operations = [ - migrations.RemoveField( - model_name='device', - name='warehouse', - ), - ] diff --git a/core/apps/management/migrations/0007_alter_expense_expense_type_delete_expensetype.py b/core/apps/management/migrations/0007_alter_expense_expense_type_delete_expensetype.py deleted file mode 100644 index 2dda04e..0000000 --- a/core/apps/management/migrations/0007_alter_expense_expense_type_delete_expensetype.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 07:49 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0006_remove_device_warehouse'), - ] - - operations = [ - migrations.AlterField( - model_name='expense', - name='expense_type', - field=models.CharField(choices=[('rent', 'Rent'), ('salary', 'Salary'), ('utilities', 'Utilities'), ('maintenance', 'Maintenance'), ('other', 'Other')], default='other', max_length=20), - ), - migrations.DeleteModel( - name='ExpenseType', - ), - ] diff --git a/core/apps/management/migrations/0008_alter_expense_expense_type.py b/core/apps/management/migrations/0008_alter_expense_expense_type.py deleted file mode 100644 index 6f2bbe1..0000000 --- a/core/apps/management/migrations/0008_alter_expense_expense_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 07:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0007_alter_expense_expense_type_delete_expensetype'), - ] - - operations = [ - migrations.AlterField( - model_name='expense', - name='expense_type', - field=models.CharField(choices=[('rent', 'Ijara'), ('salary', 'Maosh'), ('utilities', 'Kommunal to‘lovlar'), ('maintenance', 'Texnik xizmat'), ('other', 'Boshqa')], default='other', max_length=20), - ), - ] diff --git a/core/apps/management/migrations/0009_alter_expense_expense_type.py b/core/apps/management/migrations/0009_alter_expense_expense_type.py deleted file mode 100644 index ea0c064..0000000 --- a/core/apps/management/migrations/0009_alter_expense_expense_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 07:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0008_alter_expense_expense_type'), - ] - - operations = [ - migrations.AlterField( - model_name='expense', - name='expense_type', - field=models.CharField(choices=[('rent', 'Ijara'), ('salary', 'Maosh'), ('utilities', 'Kommunal to‘lovlar'), ('maintenance', 'Texnik xizmat'), ('food', 'Oziq-ovqat'), ('transport', "Yo'lkira"), ('other', 'Boshqa')], default='other', max_length=20), - ), - ] diff --git a/core/apps/management/migrations/0010_expense_device_expense_employee_and_more.py b/core/apps/management/migrations/0010_expense_device_expense_employee_and_more.py deleted file mode 100644 index 000b197..0000000 --- a/core/apps/management/migrations/0010_expense_device_expense_employee_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 08:03 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0009_alter_expense_expense_type'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AddField( - model_name='expense', - name='device', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='management.device'), - ), - migrations.AddField( - model_name='expense', - name='employee', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='salaries', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='expense', - name='expense_type', - field=models.CharField(choices=[('rent', 'Ijara'), ('salary', 'Maosh'), ('utilities', 'Kommunal to‘lovlar'), ('maintenance', 'Texnik xizmat'), ('food', 'Oziq-ovqat'), ('transport', "Yo'lkira"), ('buy_toys', 'Oʻyinchoqlar sotib olish'), ('other', 'Boshqa')], default='other', max_length=20), - ), - ] diff --git a/core/apps/management/migrations/0011_alter_expense_confirmed_by.py b/core/apps/management/migrations/0011_alter_expense_confirmed_by.py deleted file mode 100644 index 17a48b2..0000000 --- a/core/apps/management/migrations/0011_alter_expense_confirmed_by.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 08:04 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0010_expense_device_expense_employee_and_more'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AlterField( - model_name='expense', - name='confirmed_by', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='confirmed_expenses', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/core/apps/management/migrations/0012_remove_income_reported_by_income_created_by_and_more.py b/core/apps/management/migrations/0012_remove_income_reported_by_income_created_by_and_more.py deleted file mode 100644 index 965a120..0000000 --- a/core/apps/management/migrations/0012_remove_income_reported_by_income_created_by_and_more.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-05 09:37 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0011_alter_expense_confirmed_by'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.RemoveField( - model_name='income', - name='reported_by', - ), - migrations.AddField( - model_name='income', - name='created_by', - field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='created_incomes', to=settings.AUTH_USER_MODEL), - preserve_default=False, - ), - migrations.AddField( - model_name='income', - name='is_confirmed', - field=models.BooleanField(default=False), - ), - migrations.AlterField( - model_name='income', - name='confirmed_by', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='confirmed_incomes', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='income', - name='device', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='incomes', to='management.device'), - ), - ] diff --git a/core/apps/management/migrations/0013_rename_name_device_address_remove_device_monthly_fee_and_more.py b/core/apps/management/migrations/0013_rename_name_device_address_remove_device_monthly_fee_and_more.py deleted file mode 100644 index 59e8a43..0000000 --- a/core/apps/management/migrations/0013_rename_name_device_address_remove_device_monthly_fee_and_more.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-06 07:08 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0012_remove_income_reported_by_income_created_by_and_more'), - ] - - operations = [ - migrations.RenameField( - model_name='device', - old_name='name', - new_name='address', - ), - migrations.RemoveField( - model_name='device', - name='monthly_fee', - ), - migrations.RemoveField( - model_name='device', - name='toys_count', - ), - migrations.AlterField( - model_name='toymovement', - name='movement_type', - field=models.CharField(choices=[('from_warehouse', 'Ombordan → Aparatga'), ('between_warehouses', 'Ombordan → Omborga')], max_length=30), - ), - migrations.CreateModel( - name='Rent', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('address', models.CharField(max_length=100, unique=True)), - ('due_date', models.DateField()), - ('amount', models.IntegerField()), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('device', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='device_rents', to='management.device')), - ('district', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='district_rents', to='management.district')), - ], - ), - ] diff --git a/core/apps/management/migrations/0014_alter_income_amount.py b/core/apps/management/migrations/0014_alter_income_amount.py deleted file mode 100644 index 86994ad..0000000 --- a/core/apps/management/migrations/0014_alter_income_amount.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-06 12:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0013_rename_name_device_address_remove_device_monthly_fee_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='income', - name='amount', - field=models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True), - ), - ] diff --git a/core/apps/management/migrations/0015_remove_income_confirmed_by.py b/core/apps/management/migrations/0015_remove_income_confirmed_by.py deleted file mode 100644 index 7ffd0d0..0000000 --- a/core/apps/management/migrations/0015_remove_income_confirmed_by.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 6.0.2 on 2026-02-06 12:54 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0014_alter_income_amount'), - ] - - operations = [ - migrations.RemoveField( - model_name='income', - name='confirmed_by', - ), - ] diff --git a/core/apps/management/migrations/0016_rent_created_by_rent_is_paid_rent_paid_at.py b/core/apps/management/migrations/0016_rent_created_by_rent_is_paid_rent_paid_at.py deleted file mode 100644 index 2898474..0000000 --- a/core/apps/management/migrations/0016_rent_created_by_rent_is_paid_rent_paid_at.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-12 06:57 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0015_remove_income_confirmed_by'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AddField( - model_name='rent', - name='created_by', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='created_rents', to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='rent', - name='is_paid', - field=models.BooleanField(default=False), - ), - migrations.AddField( - model_name='rent', - name='paid_at', - field=models.DateTimeField(blank=True, null=True), - ), - ] diff --git a/core/apps/management/migrations/0017_expense_comment.py b/core/apps/management/migrations/0017_expense_comment.py deleted file mode 100644 index c12e13c..0000000 --- a/core/apps/management/migrations/0017_expense_comment.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-12 09:33 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0016_rent_created_by_rent_is_paid_rent_paid_at'), - ] - - operations = [ - migrations.AddField( - model_name='expense', - name='comment', - field=models.TextField(blank=True, null=True), - ), - ] diff --git a/core/apps/management/migrations/0018_income_warehouse.py b/core/apps/management/migrations/0018_income_warehouse.py deleted file mode 100644 index f1df392..0000000 --- a/core/apps/management/migrations/0018_income_warehouse.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-12 13:27 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0017_expense_comment'), - ] - - operations = [ - migrations.AddField( - model_name='income', - name='warehouse', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='warehouse_incomes', to='management.warehouse'), - ), - ] diff --git a/core/apps/management/migrations/0019_alter_expense_expense_type.py b/core/apps/management/migrations/0019_alter_expense_expense_type.py deleted file mode 100644 index 23b726d..0000000 --- a/core/apps/management/migrations/0019_alter_expense_expense_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-13 06:42 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0018_income_warehouse'), - ] - - operations = [ - migrations.AlterField( - model_name='expense', - name='expense_type', - field=models.CharField(choices=[('salary', 'Maosh'), ('utilities', 'Kommunal to‘lovlar'), ('maintenance', 'Texnik xizmat'), ('food', 'Oziq-ovqat'), ('transport', "Yo'lkira"), ('buy_toys', 'Oʻyinchoqlar sotib olish'), ('other', 'Boshqa')], default='other', max_length=20), - ), - ] diff --git a/core/apps/management/migrations/0020_device_amount_device_due_date_device_is_paid.py b/core/apps/management/migrations/0020_device_amount_device_due_date_device_is_paid.py deleted file mode 100644 index b4fcd8e..0000000 --- a/core/apps/management/migrations/0020_device_amount_device_due_date_device_is_paid.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-13 09:30 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0019_alter_expense_expense_type'), - ] - - operations = [ - migrations.AddField( - model_name='device', - name='amount', - field=models.IntegerField(blank=True, null=True), - ), - migrations.AddField( - model_name='device', - name='due_date', - field=models.DateField(blank=True, null=True), - ), - migrations.AddField( - model_name='device', - name='is_paid', - field=models.BooleanField(default=False), - ), - ] diff --git a/core/apps/management/migrations/0021_report.py b/core/apps/management/migrations/0021_report.py deleted file mode 100644 index 9d13ac8..0000000 --- a/core/apps/management/migrations/0021_report.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-13 12:56 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0020_device_amount_device_due_date_device_is_paid'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='Report', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('quantity', models.PositiveIntegerField(default=0)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), - ('device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='management.device')), - ], - ), - ] diff --git a/core/apps/management/migrations/0022_alter_district_region.py b/core/apps/management/migrations/0022_alter_district_region.py deleted file mode 100644 index 91ba59d..0000000 --- a/core/apps/management/migrations/0022_alter_district_region.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.7 on 2026-02-17 09:17 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('management', '0021_report'), - ] - - operations = [ - migrations.AlterField( - model_name='district', - name='region', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='districts', to='management.region'), - ), - ] diff --git a/core/apps/management/models/income.py b/core/apps/management/models/income.py index 0a9543f..6ccac3c 100644 --- a/core/apps/management/models/income.py +++ b/core/apps/management/models/income.py @@ -1,12 +1,30 @@ +from decimal import Decimal from django.db import models -from .device import Device class Income(models.Model): - device = models.ForeignKey(Device, related_name='incomes',on_delete=models.PROTECT) - warehouse = models.ForeignKey("management.Warehouse", on_delete=models.PROTECT, related_name="warehouse_incomes", null=True, blank=True) + warehouse = models.ForeignKey( + "management.Warehouse", + on_delete=models.PROTECT, + related_name="warehouse_incomes" + ) - amount = models.DecimalField(max_digits=12, decimal_places=2, null=True, blank=True) + toys_count = models.PositiveIntegerField(default=0) + + price_per_toy = models.DecimalField( + max_digits=12, + decimal_places=2, + default=Decimal("0.00") + ) + + total_amount = models.DecimalField( + max_digits=14, + decimal_places=2, + editable=False, + default=Decimal("0.00") + ) - created_by = models.ForeignKey("accounts.User", on_delete=models.PROTECT, related_name="created_incomes") - is_confirmed = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) + + def save(self, *args, **kwargs): + self.total_amount = self.toys_count * self.price_per_toy + super().save(*args, **kwargs) diff --git a/core/apps/management/templates/businessman/businessman_dashboard.html b/core/apps/management/templates/businessman/businessman_dashboard.html index 3355314..b860747 100644 --- a/core/apps/management/templates/businessman/businessman_dashboard.html +++ b/core/apps/management/templates/businessman/businessman_dashboard.html @@ -6,6 +6,10 @@
+ +
🏠
+
Arendalar
+
📋
Xarajatlar
@@ -22,6 +26,11 @@
🏭
Omborlar
+ +
💰
+
Kirim Qo‘shish
+
+
👥
Foydalanuvchilar
diff --git a/core/apps/management/templates/common/create/income_create.html b/core/apps/management/templates/common/create/income_create.html index afaea13..ee0d43b 100644 --- a/core/apps/management/templates/common/create/income_create.html +++ b/core/apps/management/templates/common/create/income_create.html @@ -1,10 +1,10 @@ {% extends "base.html" %} -{% block title %}{{ title|default:"Yaratish" }}{% endblock %} +{% block title %}{{ title|default:"Kirim qo‘shish" }}{% endblock %} {% block content %}
-

{{ title|default:"Yaratish" }}

+

{{ title|default:"Kirim qo‘shish" }}

{% csrf_token %} - {% for field in form %} +
- - {{ field }} - {% if field.help_text %} - {{ field.help_text }} - {% endif %} - {% for error in field.errors %} -
{{ error }}
+ + {{ form.warehouse }} + {% for error in form.warehouse.errors %} +
{{ error }}
+ {% endfor %} +
+ + +
+ + {{ form.toys_count }} + {% for error in form.toys_count.errors %} +
{{ error }}
+ {% endfor %} +
+ + +
+ + {{ form.price_per_toy }} + {% for error in form.price_per_toy.errors %} +
{{ error }}
{% endfor %}
- {% endfor %}
- + +{% if is_employee %}
+{% endif %} +{% if is_employee %} +{% endif %} {% endblock %} \ No newline at end of file diff --git a/core/apps/management/templates/common/lists/income_list.html b/core/apps/management/templates/common/lists/income_list.html index 112f2f3..9606667 100644 --- a/core/apps/management/templates/common/lists/income_list.html +++ b/core/apps/management/templates/common/lists/income_list.html @@ -3,90 +3,67 @@ {% block title %}Kirimlar{% endblock %} {% block content %} -

{{ title|default:"Kirimlar" }}

+
+

{{ title|default:"Kirimlar" }}

+ + {% if role == "businessman" %} +
+ + Yaratish + + {% endif %} +
+ +
{% for income in incomes %}
-
Miqdor: {{ income.amount|default:"-" }}
-
Aparat: {% if income.device %}{{ income.device.address }}{% else %}-{% endif %}
-
Yaratgan: {{ income.created_by.get_full_name }}
-
Yaratilgan sana: {{ income.created_at|date:"d.m.Y H:i" }}
- {% if role == "manager" or role == "businessman" %} +
+ Ombor: {{ income.warehouse }} +
+
+ O‘yinchoqlar soni: {{ income.toys_count }} +
+ +
+ Bir dona narxi: {{ income.price_per_toy }} +
+ +
+ Jami summa: + + {{ income.total_amount }} + +
+ +
+ Sana: + {{ income.created_at|date:"d.m.Y H:i" }} +
+ + {% if role == "businessman" %} {% endif %} +
{% empty %} -

Hech narsa topilmadi

+

+ Hech narsa topilmadi +

{% endfor %}
- - -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/core/apps/management/templates/common/lists/toy_movement_statistics.html b/core/apps/management/templates/common/lists/toy_movement_statistics.html new file mode 100644 index 0000000..5b55c64 --- /dev/null +++ b/core/apps/management/templates/common/lists/toy_movement_statistics.html @@ -0,0 +1,261 @@ +{% extends "base.html" %} +{% block title %}ToyMovement Statistikasi{% endblock %} +{% block content %} + +
+
+

ToyMovement Statistikasi

+

Qurilmalar bo'yicha harakat ro'yxati

+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + Tozalash +
+
+
+ + + {% if movements %} +
+ + + + + + + + + + + {% for movement in movements %} + + + + + + + {% endfor %} + +
#QurilmaMiqdorSana
{{ forloop.counter }}{{ movement.device.address|default:"—" }}{{ movement.quantity }}{{ movement.created_at|date:"d.m.Y H:i" }}
+
+

Jami: {{ movements.count }} ta yozuv

+ {% else %} +
+

⚠️ Hech qanday ma'lumot topilmadi.

+
+ {% endif %} + + ← Orqaga qaytish +
+ + + +{% endblock %} \ No newline at end of file diff --git a/core/apps/management/templates/employee/employee_dashboard.html b/core/apps/management/templates/employee/employee_dashboard.html index e255d1d..6199801 100644 --- a/core/apps/management/templates/employee/employee_dashboard.html +++ b/core/apps/management/templates/employee/employee_dashboard.html @@ -18,9 +18,9 @@
📦
Oʻyinchoq harakatlari
- +
📊
-
Yakuniy Hisobot
+
Hisobotlar
diff --git a/core/apps/management/templates/manager/manager_dashboard.html b/core/apps/management/templates/manager/manager_dashboard.html index 3d934c2..78018aa 100644 --- a/core/apps/management/templates/manager/manager_dashboard.html +++ b/core/apps/management/templates/manager/manager_dashboard.html @@ -5,6 +5,10 @@
+ +
🏠
+
Arendalar
+
📋
Xarajatlar
diff --git a/core/apps/management/urls.py b/core/apps/management/urls.py index bd896bc..7fd76bc 100644 --- a/core/apps/management/urls.py +++ b/core/apps/management/urls.py @@ -26,7 +26,7 @@ urlpatterns = [ path("list/user/", views.user_list, name="user_list"), path("list/toy-movement/", views.toy_movement_list, name="toy_movement_list"), path("list/reports/", views.report_list, name="report_list"), - + path("list/toy-movement-statistics/", views.toy_movement_statistics, name="toy_movement_statistics"), # Edit path("edit/device//", views.edit_device, name="edit_device"), path("edit/income//", views.edit_income, name="edit_income"), diff --git a/core/apps/management/views/common/create.py b/core/apps/management/views/common/create.py index 8d52ccd..144a0aa 100644 --- a/core/apps/management/views/common/create.py +++ b/core/apps/management/views/common/create.py @@ -36,19 +36,21 @@ def create_device(request): @login_required -@role_required(["employee"]) +@role_required(["businessman"]) def create_income(request): if request.method == "POST": form = IncomeForm(request.POST, user=request.user) if form.is_valid(): - income = form.save(commit=False) - if request.user.role == "employee": - income.amount = None - income.save() + form.save() return redirect("income_list") else: form = IncomeForm(user=request.user) - return render(request, "common/create/income_create.html", {"form": form}) + + return render( + request, + "common/create/income_create.html", + {"form": form, "title": "Kirim qo'shish"} + ) @login_required @role_required(['manager', 'businessman']) diff --git a/core/apps/management/views/common/list.py b/core/apps/management/views/common/list.py index 3e4e7fe..7761f45 100644 --- a/core/apps/management/views/common/list.py +++ b/core/apps/management/views/common/list.py @@ -110,30 +110,43 @@ def toy_movement_list(request): return render(request, "common/lists/toy_movement_list.html", context) @login_required -@role_required(["manager", "businessman"]) +@role_required(["businessman"]) def income_list(request): if request.user.role == "businessman": incomes = Income.objects.all() - elif request.user.role == "manager": - incomes = Income.objects.filter(warehouse__region=request.user.region) - return render(request, "common/create/income_create.html", {"incomes": incomes}) + return render( + request, + "common/lists/income_list.html", # ✅ correct template + { + "incomes": incomes, + "role": request.user.role, # ✅ important + } + ) + @login_required -@role_required(["employee"]) +@role_required(["employee", "businessman", "manager"]) def device_payment_list(request): - # Employee only sees devices in his region - devices = Device.objects.filter( - district__region=request.user.region - ).order_by("due_date") + user = request.user + + if user.role == "employee": + # Employee only sees devices in his region + devices = Device.objects.filter( + district__region=user.region + ).order_by("due_date") + else: + # Businessman and manager see ALL devices + devices = Device.objects.all().order_by("due_date") return render( request, "common/lists/device_payment_list.html", { "devices": devices, - "title": "Arendalar" + "title": "Arendalar", + "is_employee": user.role == "employee", } ) @@ -167,3 +180,30 @@ def report_list(request): "title": "Hisobotlar" } ) + +@login_required +@role_required(["employee"]) +def toy_movement_statistics(request): + movements = ToyMovement.objects.select_related("device").order_by("-created_at") + + # Date filtering + date_from = request.GET.get("date_from") + date_to = request.GET.get("date_to") + device_id = request.GET.get("device") + + if date_from: + movements = movements.filter(created_at__date__gte=date_from) + if date_to: + movements = movements.filter(created_at__date__lte=date_to) + if device_id: + movements = movements.filter(device_id=device_id) + + devices = Device.objects.all().order_by("address") + + return render(request, "common/lists/toy_movement_statistics.html", { + "movements": movements, + "devices": devices, + "date_from": date_from or "", + "date_to": date_to or "", + "selected_device": device_id or "", + }) \ No newline at end of file diff --git a/core/apps/shared/migrations/0001_initial.py b/core/apps/shared/migrations/0001_initial.py index 636abac..5756b02 100644 --- a/core/apps/shared/migrations/0001_initial.py +++ b/core/apps/shared/migrations/0001_initial.py @@ -1,5 +1,6 @@ -# Generated by Django 5.1.3 on 2025-07-11 15:00 +# Generated by Django 5.2.7 on 2026-02-18 08:13 +import django.contrib.postgres.fields import django.db.models.deletion from django.db import migrations, models @@ -16,7 +17,11 @@ class Migration(migrations.Migration): name='SettingsModel', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), ('key', models.CharField(verbose_name='key')), + ('is_public', models.BooleanField(default=False, verbose_name='is public')), + ('description', models.TextField(blank=True, null=True, verbose_name='description')), ], options={ 'verbose_name': 'Settings', @@ -28,8 +33,8 @@ class Migration(migrations.Migration): name='OptionsModel', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('key', models.CharField(verbose_name='key')), - ('value', models.CharField(verbose_name='value')), + ('key', models.CharField(max_length=255, verbose_name='key')), + ('value', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255, verbose_name='value'), size=None, verbose_name='value')), ('settings', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='options', to='shared.settingsmodel', verbose_name='settings')), ], options={ diff --git a/core/apps/shared/migrations/0002_settingsmodel_created_at_settingsmodel_description_and_more.py b/core/apps/shared/migrations/0002_settingsmodel_created_at_settingsmodel_description_and_more.py deleted file mode 100644 index 9d512b7..0000000 --- a/core/apps/shared/migrations/0002_settingsmodel_created_at_settingsmodel_description_and_more.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generated by Django 5.1.3 on 2025-07-12 05:19 - -import django.contrib.postgres.fields -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('shared', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='settingsmodel', - name='created_at', - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), - preserve_default=False, - ), - migrations.AddField( - model_name='settingsmodel', - name='description', - field=models.TextField(blank=True, null=True, verbose_name='description'), - ), - migrations.AddField( - model_name='settingsmodel', - name='is_public', - field=models.BooleanField(default=False, verbose_name='is public'), - ), - migrations.AddField( - model_name='settingsmodel', - name='updated_at', - field=models.DateTimeField(auto_now=True), - ), - migrations.AlterField( - model_name='optionsmodel', - name='key', - field=models.CharField(max_length=255, verbose_name='key'), - ), - migrations.AlterField( - model_name='optionsmodel', - name='value', - field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255, verbose_name='value'), size=None, verbose_name='value'), - ), - ]