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,27 +1,42 @@
from django.db.models import F, Sum
from core.apps.management.forms import DeviceForm, IncomeForm, WarehouseForm, UserCreateForm, ExpenseFormEmployee, \
ExpenseFormManager, ExpenseFormBusinessman
ExpenseFormManager, ExpenseFormBusinessman, ReportForm
from django.db import transaction
from django.shortcuts import render, redirect
from core.apps.management.forms import ToyMovementForm, ToyMovementFormEmployee
from django.contrib.auth.decorators import login_required
from core.apps.management.decorators import role_required
from core.apps.management.forms import UserCreateFormManagerToEmployee, UserCreateFormBusinessman
from core.apps.management.models import ToyMovement
from core.apps.management.forms.RentForm import RentForm
from core.apps.management.models import ToyMovement, Warehouse, Report
@login_required
@role_required(["manager", "businessman"])
def create_device(request):
form = DeviceForm(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return redirect("dashboard")
return render(request, "common/create/device_create.html", {
"form": form,
"title": "Aparat Yaratish"
})
user = request.user
if request.method == "POST":
form = DeviceForm(request.POST, user=user)
if form.is_valid():
form.save()
return redirect("dashboard")
else:
form = DeviceForm(user=user)
return render(
request,
"common/create/device_create.html",
{
"form": form,
"title": "Aparat Yaratish"
}
)
@login_required
@role_required(["employee"])
def create_income(request):
if request.method == "POST":
form = IncomeForm(request.POST, user=request.user)
@@ -35,6 +50,24 @@ def create_income(request):
form = IncomeForm(user=request.user)
return render(request, "common/create/income_create.html", {"form": form})
@login_required
@role_required(['manager', 'businessman'])
def create_income_manager_and_businessman(request):
if request.method == "POST":
form = IncomeForm(request.POST, user=request.user)
if form.is_valid():
with transaction.atomic():
income = form.save(commit=False)
income.created_by = request.user
income.save()
warehouse = income.warehouse
warehouse.toys_count += income.amount
warehouse.save()
return redirect("common/create/income_create.html")
else:
form = IncomeForm(user=request.user)
return render(request=request, template_name="common/create/income_create.html", context={"form": form})
@login_required
def create_expense(request):
@@ -111,110 +144,239 @@ def create_user(request):
"title": "Foydalanuvchi yaratish",
})
@login_required
def create_toy_movement(request):
user = request.user
# Choose form based on role
form_class = ToyMovementFormEmployee if user.role == "employee" else ToyMovementForm
if user.role == "employee":
form_class = ToyMovementFormEmployee
else:
form_class = ToyMovementForm
if request.method == "POST":
form = form_class(request.POST, user=user)
if form.is_valid():
with transaction.atomic():
movement = form.save(commit=False)
# Stock validation
from_wh = movement.from_warehouse
if from_wh.toys_count < movement.quantity:
form.add_error("quantity", "Not enough toys in warehouse.")
return render(
request,
"common/create/toy_movement_create.html",
{"form": form, "user_role": user.role}
quantity = form.cleaned_data["quantity"]
if user.role == "employee":
# Auto determine warehouse by region
from_wh = Warehouse.objects.select_for_update().filter(
region=user.region
).first()
if not from_wh:
form.add_error(None, "No warehouse assigned to your region.")
return render(request,
"common/create/toy_movement_create.html",
{"form": form})
if from_wh.toys_count < quantity:
form.add_error("quantity", "Not enough toys in warehouse.")
return render(request,
"common/create/toy_movement_create.html",
{"form": form})
# Deduct stock
Warehouse.objects.filter(pk=from_wh.pk).update(
toys_count=F("toys_count") - quantity
)
# Deduct from source warehouse
from_wh.toys_count -= movement.quantity
from_wh.save()
movement = form.save(commit=False)
movement.movement_type = "from_warehouse"
movement.from_warehouse = from_wh
movement.to_warehouse = None
movement.created_by = user
movement.save()
# Add to destination warehouse if moving between warehouses
if movement.movement_type == "between_warehouses" and movement.to_warehouse:
to_wh = movement.to_warehouse
to_wh.toys_count += movement.quantity
to_wh.save()
else:
# Manager / Businessman normal logic
from_wh = form.cleaned_data["from_warehouse"]
movement_type = form.cleaned_data["movement_type"]
to_wh = form.cleaned_data.get("to_warehouse")
# Set creator
movement.created_by = user
movement.save()
from_wh = Warehouse.objects.select_for_update().get(pk=from_wh.pk)
if from_wh.toys_count < quantity:
form.add_error("quantity", "Not enough toys in warehouse.")
return render(request,
"common/create/toy_movement_create.html",
{"form": form})
Warehouse.objects.filter(pk=from_wh.pk).update(
toys_count=F("toys_count") - quantity
)
if movement_type == "between_warehouses" and to_wh:
to_wh = Warehouse.objects.select_for_update().get(pk=to_wh.pk)
Warehouse.objects.filter(pk=to_wh.pk).update(
toys_count=F("toys_count") + quantity
)
movement = form.save(commit=False)
movement.created_by = user
movement.save()
return redirect("dashboard")
else:
form = form_class(user=user)
return render(
request,
"common/create/toy_movement_create.html",
{"form": form, "user_role": user.role}
{"form": form}
)
@login_required
@role_required(["manager", "businessman"])
def create_toy_movement_auto(request):
user = request.user
# Only employees can use this auto-creation
if request.method == "POST":
# We force movement_type to "between_warehouses"
movement = ToyMovement(
movement_type="between_warehouses",
from_warehouse=user.warehouse,
to_warehouse_id=request.POST.get("to_warehouse"),
device=None, # not used for between_warehouses
quantity=int(request.POST.get("quantity", 0)),
created_by=user
)
form = ToyMovementForm(request.POST, user=user)
# Stock validation
from_wh = movement.from_warehouse
if from_wh.toys_count < movement.quantity:
form = ToyMovementForm(user=user) # just render empty form with message
return render(
request,
"common/create/toy_movement_create.html",
{
"form": form,
"user_role": user.role,
"error": "Not enough toys in warehouse."
}
)
if form.is_valid():
with transaction.atomic():
# Get cleaned data
from_wh = form.cleaned_data.get("from_warehouse")
to_wh = form.cleaned_data.get("to_warehouse")
movement_type = form.cleaned_data.get("movement_type")
quantity = form.cleaned_data.get("quantity")
with transaction.atomic():
# Update warehouse stock
from_wh.toys_count -= movement.quantity
from_wh.save()
# Validate warehouse exists
if not from_wh:
form.add_error("from_warehouse", "Source warehouse is required.")
return render(request, "common/create/toy_movement_create.html", {"form": form})
# Save movement
movement.save()
# Lock and get fresh warehouse data
from_wh = Warehouse.objects.select_for_update().get(pk=from_wh.pk)
return redirect("dashboard")
# Check stock
if from_wh.toys_count < quantity:
form.add_error("quantity", "Not enough toys in warehouse.")
return render(request, "common/create/toy_movement_create.html", {"form": form})
# GET request → render the create form
form = ToyMovementForm(user=user)
# Pre-fill movement_type and from_warehouse
form.fields["movement_type"].initial = "between_warehouses"
form.fields["from_warehouse"].initial = user.warehouse
# Optionally, disable editing these fields
form.fields["movement_type"].widget.attrs["readonly"] = True
form.fields["from_warehouse"].widget.attrs["readonly"] = True
# Deduct from source warehouse
Warehouse.objects.filter(pk=from_wh.pk).update(
toys_count=F("toys_count") - quantity
)
# Add to destination warehouse if between_warehouses
if movement_type == "between_warehouses" and to_wh:
to_wh = Warehouse.objects.select_for_update().get(pk=to_wh.pk)
Warehouse.objects.filter(pk=to_wh.pk).update(
toys_count=F("toys_count") + quantity
)
# Save movement
movement = form.save(commit=False)
movement.created_by = user
movement.save()
return redirect("toy_movement_list")
else:
# Form has errors, display them
return render(request, "common/create/toy_movement_create.html", {"form": form})
else:
# GET request → render the create form
form = ToyMovementForm(user=user)
return render(
request,
"common/create/toy_movement_create.html",
{"form": form, "user_role": user.role}
{"form": form}
)
@login_required
@role_required(["manager", "businessman"])
def create_rent(request):
if request.method == "POST":
form = RentForm(request.POST)
if form.is_valid():
rent = form.save(commit=False)
rent.created_by = request.user
rent.save()
return redirect("dashboard")
else:
form = RentForm()
return render(request, "common/create/rent_create.html", {"form":form, "title":"Create Rent"})
@login_required
@role_required(["employee"])
def create_report(request):
if request.method == "POST":
form = ReportForm(request.POST, user=request.user)
if form.is_valid():
# 🔥 Employee MUST have warehouse
if not request.user.warehouse:
form.add_error(None, "Sizga ombor biriktirilmagan.")
return render(
request,
"common/create/report_create.html",
{"form": form, "title": "Yakuniy Hisobot"}
)
device = form.cleaned_data["device"]
entered_quantity = form.cleaned_data["quantity"]
with transaction.atomic():
# ✅ 1. Save last entered quantity as ToyMovement
ToyMovement.objects.create(
movement_type="from_warehouse",
from_warehouse=request.user.warehouse,
device=device,
quantity=entered_quantity,
created_by=request.user,
)
# ✅ 2. Find last report for this device
last_report = Report.objects.filter(
device=device
).order_by("-created_at").first()
if last_report:
last_time = last_report.created_at
total_since_last = ToyMovement.objects.filter(
device=device,
created_at__gt=last_time
).aggregate(
total=Sum("quantity")
)["total"] or 0
else:
total_since_last = ToyMovement.objects.filter(
device=device
).aggregate(
total=Sum("quantity")
)["total"] or 0
# ✅ 3. Create Report
Report.objects.create(
device=device,
quantity=total_since_last,
created_by=request.user
)
return redirect("employee_dashboard")
else:
form = ReportForm(user=request.user)
return render(
request,
"common/create/report_create.html",
{
"form": form,
"title": "Yakuniy Hisobot"
}
)

View File

@@ -2,7 +2,8 @@ from django.contrib.auth.decorators import login_required
from core.apps.accounts.models import User
from core.apps.management.forms import DeviceForm, IncomeForm, ExpenseForm, WarehouseForm, UserCreateForm, \
ToyMovementEmployeeForm, ToyMovementForm, ExpenseFormEmployee, ExpenseFormManager, ExpenseFormBusinessman
ToyMovementEmployeeForm, ToyMovementForm, ExpenseFormEmployee, ExpenseFormManager, ExpenseFormBusinessman, \
DevicePaymentForm
from django.shortcuts import render, redirect, get_object_or_404
from core.apps.management.models import Device, Income, Expense, Warehouse, ToyMovement
from django.db import transaction
@@ -30,11 +31,11 @@ def edit_income(request, pk):
form = IncomeForm(request.POST, instance=income)
if form.is_valid():
form.save()
return redirect("income_list")
return redirect("common/create/income_create.html")
else:
form = IncomeForm(instance=income)
return render(request, "common/edit/income_edit.html", {
return render(request, "common/create/income_create.html", {
"form": form,
"title": "Kirimni tahrirlash"
})
@@ -125,6 +126,22 @@ def edit_user(request, pk):
"title": "Foydalanuvchini tahrirlash",
})
@login_required
@role_required(["employee"])
def mark_device_paid(request, pk):
device = get_object_or_404(Device, pk=pk)
# Security check
if device.district.region != request.user.region:
return redirect("device_payment_list")
if request.method == "POST":
device.is_paid = True
device.save()
return redirect("device_payment_list")
# @role_required(["businessman"])
# @login_required
# def edit_toy_movement(request, pk):

View File

@@ -1,6 +1,6 @@
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from core.apps.management.models import Device, Income, Expense, Warehouse, ToyMovement
from core.apps.management.models import Device, Income, Expense, Warehouse, ToyMovement, Report
from core.apps.accounts.models import User
from core.apps.management.decorators import role_required
@@ -39,14 +39,34 @@ def device_list(request):
@login_required
def expense_list(request):
expenses = Expense.objects.select_related("created_by", "confirmed_by").order_by("-created_at")
user = request.user
expenses = Expense.objects.select_related(
"created_by",
"confirmed_by"
).order_by("-created_at")
# 🔐 ROLE-BASED FILTERING
if user.role == "employee":
expenses = expenses.filter(created_by=user)
elif user.role == "manager":
# Optional: show only region expenses
expenses = expenses.filter(
created_by__region=user.region
)
# businessman sees everything (no filter)
context = {
"expenses": expenses,
"role": request.user.role,
"role": user.role,
}
return render(request, "common/lists/expense_list.html", context)
@login_required
def income_list(request):
incomes = Income.objects.select_related("device", "created_by", "created_by__region").order_by("-created_at")
@@ -87,4 +107,63 @@ def toy_movement_list(request):
"toy_movements": toy_movements,
"role": request.user.role,
}
return render(request, "common/lists/toy_movement_list.html", context)
return render(request, "common/lists/toy_movement_list.html", context)
@login_required
@role_required(["manager", "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})
@login_required
@role_required(["employee"])
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")
return render(
request,
"common/lists/device_payment_list.html",
{
"devices": devices,
"title": "Arendalar"
}
)
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.db.models import Q
from core.apps.management.models import Report
from core.apps.management.decorators import role_required
@login_required
@role_required(['manager', 'businessman'])
def report_list(request):
reports = (
Report.objects
.select_related("device", "device__district", "created_by")
.order_by("-created_at")
)
if request.user.role == "manager":
reports = reports.filter(
device__district__region=request.user.region
)
return render(
request,
"common/lists/report_list.html",
{
"reports": reports,
"title": "Hisobotlar"
}
)