from django.db.models import F, Sum from core.apps.management.forms import DeviceForm, IncomeForm, WarehouseForm, UserCreateForm, ExpenseFormEmployee, \ 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.forms.RentForm import RentForm from core.apps.management.models import ToyMovement, Warehouse, Report @login_required @role_required(["manager", "businessman"]) def create_device(request): 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(["businessman"]) def create_income(request): if request.method == "POST": form = IncomeForm(request.POST, user=request.user) if form.is_valid(): form.save() return redirect("income_list") else: form = IncomeForm(user=request.user) return render( request, "common/create/income_create.html", {"form": form, "title": "Kirim qo'shish"} ) @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): user = request.user # select form based on role if user.role == "employee": form_class = ExpenseFormEmployee elif user.role == "manager": form_class = ExpenseFormManager else: # businessman or superuser form_class = ExpenseFormBusinessman if request.method == "POST": form = form_class(request.POST) if form.is_valid(): with transaction.atomic(): expense = form.save(commit=False) expense.created_by = user # AUTO CONFIRM for manager & businessman if user.role in ["manager", "businessman"]: expense.is_confirmed = True expense.confirmed_by = user expense.save() return redirect("dashboard") else: form = form_class() return render(request, "common/create/expense_create.html", { "form": form, "title": "Xarajat qoʻshish", "user_role": user.role }) @login_required @role_required(["businessman"]) def create_warehouse(request): form = WarehouseForm(request.POST or None) if form.is_valid(): form.save() return redirect("businessman_dashboard") return render(request, "common/create/warehouse_create.html", { "form": form, "title": "Sklad Yaratish" }) @login_required @role_required(["manager", "businessman"]) def create_user(request): if request.user.role == "businessman": form_class = UserCreateFormBusinessman form_kwargs = {} redirect_to = "businessman_dashboard" else: # manager form_class = UserCreateFormManagerToEmployee form_kwargs = {"manager": request.user} redirect_to = "manager_dashboard" form = form_class(request.POST or None, **form_kwargs) if form.is_valid(): form.save() return redirect(redirect_to) return render(request, "common/create/user_create.html", { "form": form, "title": "Foydalanuvchi yaratish", }) @login_required def create_toy_movement(request): user = request.user 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(): 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 ) 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() 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") 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} ) @login_required @role_required(["manager", "businessman"]) def create_toy_movement_auto(request): user = request.user if request.method == "POST": form = ToyMovementForm(request.POST, user=user) 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") # 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}) # Lock and get fresh warehouse data from_wh = Warehouse.objects.select_for_update().get(pk=from_wh.pk) # 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}) # 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} ) @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" } )