126 lines
4.6 KiB
Python
126 lines
4.6 KiB
Python
import json
|
|
from django.shortcuts import render, get_object_or_404, redirect
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.http import require_POST
|
|
from django.contrib.auth.decorators import login_required
|
|
from django.core.exceptions import PermissionDenied
|
|
from financial.models import Contract, ChargeNumber
|
|
from .models import Item
|
|
|
|
def is_developer(user):
|
|
return user.is_active and (user.is_superuser or user.groups.filter(name__iexact='developer').exists())
|
|
|
|
def developer_required(view_func):
|
|
def _wrapped_view(request, *args, **kwargs):
|
|
if is_developer(request.user):
|
|
return view_func(request, *args, **kwargs)
|
|
raise PermissionDenied
|
|
return _wrapped_view
|
|
|
|
@login_required
|
|
def board_view(request):
|
|
items = Item.objects.select_related('charge_number', 'charge_number__contract').all()
|
|
todo_items = items.filter(status=Item.Status.TODO)
|
|
in_progress_items = items.filter(status=Item.Status.IN_PROGRESS)
|
|
done_items = items.filter(status=Item.Status.DONE)
|
|
|
|
context = {
|
|
'todo_items': todo_items,
|
|
'in_progress_items': in_progress_items,
|
|
'done_items': done_items,
|
|
'statuses': Item.Status.choices,
|
|
'qbd_charge_numbers': ChargeNumber.objects.filter(charge_number_type='QBD'),
|
|
'is_developer': is_developer(request.user),
|
|
}
|
|
return render(request, 'planning/board.html', context)
|
|
|
|
@login_required
|
|
def backlog_view(request):
|
|
items = Item.objects.select_related('charge_number', 'charge_number__contract').all().order_by('-created_at')
|
|
|
|
status_filter = request.GET.get('status')
|
|
if status_filter and status_filter in dict(Item.Status.choices):
|
|
items = items.filter(status=status_filter)
|
|
|
|
context = {
|
|
'items': items,
|
|
'statuses': Item.Status.choices,
|
|
'qbd_charge_numbers': ChargeNumber.objects.filter(charge_number_type='QBD'),
|
|
'is_developer': is_developer(request.user),
|
|
}
|
|
return render(request, 'planning/backlog.html', context)
|
|
|
|
@login_required
|
|
@developer_required
|
|
@require_POST
|
|
def create_item(request):
|
|
title = request.POST.get('title')
|
|
description = request.POST.get('description', '')
|
|
charge_number_id = request.POST.get('charge_number')
|
|
next_url = request.POST.get('next', 'planning:board_view')
|
|
if title:
|
|
max_order = Item.objects.filter(status=Item.Status.TODO).count()
|
|
item = Item.objects.create(title=title, description=description, status=Item.Status.TODO, order=max_order)
|
|
if charge_number_id:
|
|
item.charge_number_id = charge_number_id
|
|
item.save()
|
|
return redirect(next_url)
|
|
|
|
@login_required
|
|
def item_detail(request, pk):
|
|
item = get_object_or_404(Item.objects.select_related('charge_number', 'charge_number__contract'), pk=pk)
|
|
context = {
|
|
'item': item,
|
|
'statuses': Item.Status.choices,
|
|
'qbd_charge_numbers': ChargeNumber.objects.filter(charge_number_type='QBD'),
|
|
'is_developer': is_developer(request.user),
|
|
}
|
|
return render(request, 'planning/partials/item_detail.html', context)
|
|
|
|
@login_required
|
|
@developer_required
|
|
@require_POST
|
|
def edit_item(request, pk):
|
|
item = get_object_or_404(Item, pk=pk)
|
|
item.title = request.POST.get('title', item.title)
|
|
item.description = request.POST.get('description', item.description)
|
|
item.status = request.POST.get('status', item.status)
|
|
charge_number_id = request.POST.get('charge_number')
|
|
if charge_number_id:
|
|
item.charge_number_id = charge_number_id
|
|
else:
|
|
item.charge_number = None
|
|
item.save()
|
|
next_url = request.POST.get('next', 'planning:board_view')
|
|
return redirect(next_url)
|
|
|
|
@login_required
|
|
@developer_required
|
|
@require_POST
|
|
def delete_item(request, pk):
|
|
item = get_object_or_404(Item, pk=pk)
|
|
item.delete()
|
|
next_url = request.POST.get('next', 'planning:board_view')
|
|
return redirect(next_url)
|
|
|
|
@login_required
|
|
@developer_required
|
|
@require_POST
|
|
def update_item_status(request, pk):
|
|
try:
|
|
data = json.loads(request.body)
|
|
new_status = data.get('status')
|
|
new_order = data.get('order')
|
|
|
|
item = get_object_or_404(Item, pk=pk)
|
|
|
|
if new_status and new_status in dict(Item.Status.choices):
|
|
item.status = new_status
|
|
if new_order is not None:
|
|
item.order = new_order
|
|
item.save()
|
|
return JsonResponse({'status': 'success'})
|
|
return JsonResponse({'status': 'error', 'message': 'Invalid status'}, status=400)
|
|
except Exception as e:
|
|
return JsonResponse({'status': 'error', 'message': str(e)}, status=400)
|