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"
}
)