Initial commit

This commit is contained in:
Abdulaziz Axmadaliyev
2026-02-17 19:05:54 +05:00
parent 493cb58222
commit 3691e2d068
56 changed files with 3546 additions and 893 deletions

View File

@@ -1,19 +1,31 @@
from django import forms
from ..models import Device, District
class DeviceForm(forms.ModelForm):
class Meta:
model = Device
fields = ["address", "district"]
fields = ["address", "district", "amount", "due_date"]
labels = {
"address": "Manzil",
"district": "Tuman",
"amount": "Summa",
"due_date": "Tolov muddati",
}
widgets = {
"due_date": forms.DateInput(
attrs={"type": "date"}
)
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None) # get the user from kwargs
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
if user is not None:
if user:
if user.role == "manager":
# Manager: only districts in the same region
self.fields['district'].queryset = District.objects.filter(region=user.region)
self.fields["district"].queryset = District.objects.filter(
region=user.region
)
else:
# Businessman: show all districts
self.fields['district'].queryset = District.objects.all()
self.fields["district"].queryset = District.objects.all()

View File

@@ -0,0 +1,24 @@
from django import forms
from ..models import Device
class DevicePaymentForm(forms.ModelForm):
class Meta:
model = Device
fields = ["is_paid"] # 🔥 Only this field
widgets = {
"is_paid": forms.CheckboxInput(attrs={"class": "form-check-input"})
}
def save(self, commit=True):
instance = super().save(commit=False)
# 🔥 Ensure employee can ONLY mark as True
if not instance.is_paid:
instance.is_paid = True
if commit:
instance.save()
return instance

View File

@@ -2,42 +2,75 @@ from django import forms
from ..models import Expense, Device
from core.apps.accounts.models import User
# Base form
# =========================
# Base Form
# =========================
class BaseExpenseForm(forms.ModelForm):
class Meta:
model = Expense
fields = ["amount", "expense_type", "employee", "device"]
fields = ["amount", "expense_type", "employee", "device", "comment"]
labels = {
"amount": "Summa",
"expense_type": "Xarajat turi",
"employee": "Xodim",
"device": "Qurilma",
"comment": "Izoh",
}
widgets = {
"comment": forms.Textarea(attrs={"rows": 3})
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Show all devices
self.fields["device"].queryset = Device.objects.all()
# Show all employees
# Show only employees
self.fields["employee"].queryset = User.objects.filter(role="employee")
# Comment is optional unless expense_type == other
self.fields["comment"].required = False
def clean(self):
cleaned_data = super().clean()
expense_type = cleaned_data.get("expense_type")
employee = cleaned_data.get("employee")
device = cleaned_data.get("device")
comment = cleaned_data.get("comment")
# OTHER requires comment
if expense_type == Expense.ExpenseType.OTHER and not comment:
self.add_error("comment", "Iltimos 'boshqa' tanlovi uchun izoh qoldiring!")
# Salary requires employee
if expense_type == Expense.ExpenseType.SALARY and not employee:
self.add_error("employee", "Employee must be set for Salary expenses.")
# Device required for rent/maintenance
if expense_type in [Expense.ExpenseType.RENT, Expense.ExpenseType.MAINTENANCE] and not device:
self.add_error("device", "Device must be set for this type of expense.")
# Maintenance requires device
if expense_type == Expense.ExpenseType.MAINTENANCE and not device:
self.add_error("device", "Device must be set for Maintenance expenses.")
return cleaned_data
# Employee form: cannot create Salary or Buy Toys
# =========================
# Employee Form
# =========================
class ExpenseFormEmployee(BaseExpenseForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Remove forbidden types for employee
forbidden = [Expense.ExpenseType.SALARY, Expense.ExpenseType.BUY_TOYS]
# Employee cannot create Salary or Buy Toys
forbidden = [
Expense.ExpenseType.SALARY,
Expense.ExpenseType.BUY_TOYS,
]
self.fields["expense_type"].choices = [
(value, label)
for value, label in Expense.ExpenseType.choices
@@ -45,11 +78,19 @@ class ExpenseFormEmployee(BaseExpenseForm):
]
# Manager form: cannot create Buy Toys
# =========================
# Manager Form
# =========================
class ExpenseFormManager(BaseExpenseForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
forbidden = [Expense.ExpenseType.BUY_TOYS]
# Manager cannot create Buy Toys
forbidden = [
Expense.ExpenseType.BUY_TOYS,
]
self.fields["expense_type"].choices = [
(value, label)
for value, label in Expense.ExpenseType.choices
@@ -57,6 +98,8 @@ class ExpenseFormManager(BaseExpenseForm):
]
# Businessman form: full access
# =========================
# Businessman Form
# =========================
class ExpenseFormBusinessman(BaseExpenseForm):
pass
pass

View File

@@ -1,10 +1,11 @@
from django import forms
from ..models import Income, Device
from ..models import Income, Device, Warehouse
class IncomeForm(forms.ModelForm):
class Meta:
model = Income
fields = ["device", "amount"]
fields = ["device", "amount", "warehouse"]
def __init__(self, *args, **kwargs):
self.user = kwargs.pop("user", None)
@@ -13,8 +14,10 @@ class IncomeForm(forms.ModelForm):
if self.user is not None:
# Filter devices
if self.user.role == "businessman":
self.fields["device"].queryset = Device.objects.all()
else: # manager or employee
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

View File

@@ -0,0 +1,61 @@
from django import forms
from core.apps.management.models import Device
class ReportForm(forms.Form):
device = forms.ModelChoiceField(
queryset=Device.objects.all(),
label="Qurilma",
required=True,
widget=forms.Select(attrs={
'class': 'form-select',
}),
error_messages={
'required': 'Qurilmani tanlang',
'invalid_choice': 'Tanlangan qurilma topilmadi'
}
)
quantity = forms.IntegerField(
min_value=1,
label="So'nggi miqdor",
required=True,
widget=forms.NumberInput(attrs={
'class': 'form-input',
'placeholder': 'Miqdorni kiriting',
'min': '1'
}),
error_messages={
'required': 'Miqdorni kiriting',
'invalid': 'Miqdor raqam bo\'lishi kerak',
'min_value': 'Miqdor 1 dan katta bo\'lishi kerak'
}
)
def __init__(self, *args, **kwargs):
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
self.user = user
# ✅ SHOW ALL DEVICES - don't filter by warehouse
# Reports need to see all devices, not just warehouse devices
self.fields["device"].queryset = Device.objects.all().order_by('address')
# Show count for debugging
device_count = self.fields["device"].queryset.count()
if device_count == 0:
self.fields["device"].help_text = "⚠️ Hech qanday qurilma topilmadi. Admindan so'rab qurilmalar qo'shing."
def clean_device(self):
device = self.cleaned_data.get('device')
if not device:
raise forms.ValidationError("Qurilmani tanlang")
return device
def clean_quantity(self):
quantity = self.cleaned_data.get('quantity')
if quantity is None:
raise forms.ValidationError("Miqdorni kiriting")
if quantity < 1:
raise forms.ValidationError("Miqdor 1 dan katta bo'lishi kerak")
return quantity

View File

@@ -2,10 +2,18 @@ from django import forms
from core.apps.management.models import ToyMovement, Warehouse, Device
from core.apps.management.choice import TOY_MOVEMENT_TYPE
class ToyMovementForm(forms.ModelForm):
class Meta:
model = ToyMovement
fields = ["movement_type", "from_warehouse", "to_warehouse", "device", "quantity"]
labels = {
"movement_type": "Harakat turi",
"from_warehouse": "Qaysi ombordan",
"to_warehouse": "Qaysi omborga",
"device": "Qurilma",
"quantity": "Soni",
}
widgets = {
"movement_type": forms.Select(choices=TOY_MOVEMENT_TYPE),
}
@@ -13,18 +21,36 @@ class ToyMovementForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
self.fields["from_warehouse"].queryset = Warehouse.objects.all()
self.fields["to_warehouse"].queryset = Warehouse.objects.all()
self.fields["device"].queryset = Device.objects.all()
def save(self, commit=True):
instance = super().save(commit=False)
def clean(self):
cleaned_data = super().clean()
if instance.movement_type == "from_warehouse":
instance.to_warehouse = None
elif instance.movement_type == "between_warehouses":
instance.device = None
movement_type = cleaned_data.get("movement_type")
from_wh = cleaned_data.get("from_warehouse")
to_wh = cleaned_data.get("to_warehouse")
device = cleaned_data.get("device")
quantity = cleaned_data.get("quantity")
if commit:
instance.save()
return instance
if not from_wh:
self.add_error("from_warehouse", "Source warehouse is required.")
if quantity and quantity <= 0:
self.add_error("quantity", "Quantity must be greater than 0.")
if movement_type == "from_warehouse":
if not device:
self.add_error("device", "Device is required for this movement type.")
cleaned_data["to_warehouse"] = None
if movement_type == "between_warehouses":
if not to_wh:
self.add_error("to_warehouse", "Destination warehouse required.")
if from_wh and to_wh and from_wh == to_wh:
self.add_error("to_warehouse", "Cannot move to the same warehouse.")
cleaned_data["device"] = None
return cleaned_data

View File

@@ -4,4 +4,9 @@ from ..models import Warehouse
class WarehouseForm(forms.ModelForm):
class Meta:
model = Warehouse
fields = ["name", "region", "toys_count"]
fields = ["name", "region", "toys_count"]
labels = {
"name": "Nomi",
"region": "Hudud",
"toys_count": "Oyinchoqlar soni",
}

View File

@@ -5,4 +5,6 @@ from .WarehouseForm import *
from .UserCreateForm import *
from .ToyMovementEmployeeForm import ToyMovementFormEmployee
from .ToyMovementForm import ToyMovementForm
from .user import *
from .user import *
from .DevicePaymentForm import *
from .ReportForm import *

View File

@@ -27,6 +27,15 @@ class BaseUserForm(forms.ModelForm):
"region",
"warehouse",
]
labels = {
"phone": "Telefon raqami",
"password": "Parol",
"role": "Lavozim",
"first_name": "Ism",
"last_name": "Familiya",
"region": "Hudud",
"warehouse": "Ombor",
}
def clean_role(self):
role = self.cleaned_data["role"]