124 lines
4.7 KiB
Python
124 lines
4.7 KiB
Python
from django.contrib import admin
|
||
from django.shortcuts import redirect
|
||
from django.urls import path, reverse
|
||
from django.utils import timezone
|
||
from django.utils.html import format_html
|
||
|
||
from .models import Claim, ClaimLog, Project
|
||
|
||
|
||
class ClaimLogInline(admin.TabularInline):
|
||
model = ClaimLog
|
||
extra = 0
|
||
readonly_fields = ("action", "from_status", "to_status", "note", "performed_by", "created_at")
|
||
can_delete = False
|
||
|
||
|
||
@admin.register(Claim)
|
||
class ClaimAdmin(admin.ModelAdmin):
|
||
list_display = ("full_name", "amount", "currency", "project", "status", "paid", "created_at", "submitted_by")
|
||
list_filter = ("status", "created_at", "project", "paid_at")
|
||
search_fields = ("full_name", "email", "description")
|
||
base_readonly = ("created_at", "updated_at", "paid_at", "paid_by", "reset_paid_button")
|
||
readonly_fields = base_readonly
|
||
inlines = [ClaimLogInline]
|
||
actions = ("mark_as_paid", "mark_as_unpaid")
|
||
|
||
@admin.display(boolean=True, description="Betald")
|
||
def paid(self, obj):
|
||
return obj.is_paid
|
||
|
||
@admin.display(description="Återställ betalning")
|
||
def reset_paid_button(self, obj):
|
||
if not obj.is_paid:
|
||
return "Ej betald"
|
||
url = reverse("admin:claims_claim_reset_payment", args=[obj.pk])
|
||
return format_html(
|
||
'<a class="button" href="{}" onclick="return confirm(\'Ta bort betalningsmarkeringen?\');">Resetta</a>',
|
||
url,
|
||
)
|
||
|
||
@admin.action(description="Markera valda som betalda")
|
||
def mark_as_paid(self, request, queryset):
|
||
count = 0
|
||
for claim in queryset.filter(status=Claim.Status.APPROVED, paid_at__isnull=True):
|
||
claim.paid_at = timezone.now()
|
||
claim.paid_by = request.user
|
||
claim.save(update_fields=["paid_at", "paid_by"])
|
||
claim.add_log(
|
||
action=ClaimLog.Action.MARKED_PAID,
|
||
performed_by=request.user,
|
||
note="Markerad som betald via Django admin.",
|
||
)
|
||
count += 1
|
||
if count:
|
||
self.message_user(request, f"{count} utlägg markerades som betalda.")
|
||
else:
|
||
self.message_user(request, "Inga utlägg markerades – kontrollera status/betalning.", level="warning")
|
||
|
||
@admin.action(description="Återställ betalningsstatus (markera som obetalda)")
|
||
def mark_as_unpaid(self, request, queryset):
|
||
count = 0
|
||
for claim in queryset.filter(paid_at__isnull=False):
|
||
claim.paid_at = None
|
||
claim.paid_by = None
|
||
claim.save(update_fields=["paid_at", "paid_by"])
|
||
claim.add_log(
|
||
action=ClaimLog.Action.MARKED_PAID,
|
||
performed_by=request.user,
|
||
note="Betalningsstatus återställd via Django admin.",
|
||
)
|
||
count += 1
|
||
if count:
|
||
self.message_user(request, f"{count} utlägg markerades som obetalda.")
|
||
else:
|
||
self.message_user(request, "Inga utlägg behövde återställas.", level="warning")
|
||
|
||
def save_model(self, request, obj, form, change):
|
||
super().save_model(request, obj, form, change)
|
||
|
||
def get_urls(self):
|
||
urls = super().get_urls()
|
||
custom_urls = [
|
||
path(
|
||
"<int:claim_id>/reset-payment/",
|
||
self.admin_site.admin_view(self.reset_payment_view),
|
||
name="claims_claim_reset_payment",
|
||
),
|
||
]
|
||
return custom_urls + urls
|
||
|
||
def reset_payment_view(self, request, claim_id):
|
||
claim = Claim.objects.filter(pk=claim_id).first()
|
||
if not claim:
|
||
self.message_user(request, "Utlägget hittades inte.", level="error")
|
||
return redirect("admin:claims_claim_changelist")
|
||
claim.paid_at = None
|
||
claim.paid_by = None
|
||
claim.save(update_fields=["paid_at", "paid_by"])
|
||
claim.add_log(
|
||
action=ClaimLog.Action.MARKED_PAID,
|
||
performed_by=request.user,
|
||
note="Betalningsstatus återställd via reset-knapp i admin.",
|
||
)
|
||
self.message_user(request, f"{claim} markerades som obetald.")
|
||
return redirect("admin:claims_claim_change", claim_id)
|
||
|
||
def get_readonly_fields(self, request, obj=None):
|
||
if obj and obj.is_paid:
|
||
return self.base_readonly + ("status", "decision_note")
|
||
return self.base_readonly
|
||
|
||
|
||
@admin.register(ClaimLog)
|
||
class ClaimLogAdmin(admin.ModelAdmin):
|
||
list_display = ("claim", "action", "from_status", "to_status", "performed_by", "created_at")
|
||
list_filter = ("action", "to_status", "created_at")
|
||
|
||
|
||
@admin.register(Project)
|
||
class ProjectAdmin(admin.ModelAdmin):
|
||
list_display = ("name", "code", "is_active", "updated_at")
|
||
list_filter = ("is_active",)
|
||
search_fields = ("name", "code")
|