Initial commit
This commit is contained in:
@@ -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": "To‘lov 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()
|
||||
|
||||
24
core/apps/management/forms/DevicePaymentForm.py
Normal file
24
core/apps/management/forms/DevicePaymentForm.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
61
core/apps/management/forms/ReportForm.py
Normal file
61
core/apps/management/forms/ReportForm.py
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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": "O‘yinchoqlar soni",
|
||||
}
|
||||
@@ -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 *
|
||||
|
||||
@@ -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"]
|
||||
|
||||
Reference in New Issue
Block a user