beneficiary list and create one

This commit is contained in:
Cayo Puigdefabregas 2025-03-13 15:24:20 +01:00
parent bc890cc49b
commit ea88d92dc3
8 changed files with 295 additions and 13 deletions

View file

@ -18,12 +18,13 @@
<i class="bi bi-tag"></i>
{% trans 'properties' %}
</a>
{% if user %}
{% if subscripted or user.is_admin %}
<a href="{% url 'lot:subscription' object.id %}" type="button" class="btn btn-green-admin">
<i class="bi bi-tag"></i>
{% trans 'Subscription' %}
</a>
{% endif %}
{% if is_circuit_manager %}
{% if donor %}
<a href="{% url 'lot:del_donor' object.id %}" type="button" class="btn btn-green-admin">
<i class="bi bi-tag"></i>
@ -36,6 +37,13 @@
</a>
{% endif %}
{% endif %}
{% if is_shop %}
<a href="{% url 'lot:beneficiary' object.id %}" type="button" class="btn btn-green-admin">
<i class="bi bi-tag"></i>
{% trans 'Beneficiary' %}
</a>
{% endif %}
{% endif %}
</div>
</div>

View file

@ -1,15 +1,13 @@
import json
from django.utils.translation import gettext_lazy as _
from django.views.generic.edit import FormView
from django.shortcuts import Http404
from django.db.models import Q
from dashboard.mixins import InventaryMixin, DetailsMixin
from evidence.models import SystemProperty
from evidence.xapian import search
from device.models import Device
from lot.models import Lot, Donor
from lot.models import Lot, LotSubscription, Donor
class UnassignedDevicesView(InventaryMixin):
@ -42,15 +40,23 @@ class LotDashboardView(InventaryMixin, DetailsMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
lot = context.get('object')
donor = Donor.objects.filter(
subscriptions = LotSubscription.objects.filter(
lot=lot,
user=self.request.user
)
is_shop = subscriptions.filter(type=LotSubscription.Type.SHOP).first()
is_circuit_manager = subscriptions.filter(
type=LotSubscription.Type.CIRCUIT_MANAGER
).first()
if donor:
context["donor"] = donor
donor = Donor.objects.filter(lot=lot).first()
context.update({
'lot': lot,
'subscripted': subscriptions.first(),
'is_circuit_manager': is_circuit_manager,
'is_shop': is_shop,
'donor': donor,
})
return context

View file

@ -2,7 +2,12 @@ from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError
from django import forms
from user.models import User
from lot.models import Lot, LotSubscription, Donor
from lot.models import (
Lot,
LotSubscription,
Beneficiary,
Donor,
)
class LotsForm(forms.Form):
@ -31,6 +36,41 @@ class LotsForm(forms.Form):
return
class BeneficiaryForm(forms.Form):
beneficiary = forms.CharField()
def __init__(self, *args, **kwargs):
self.shop = kwargs.pop("shop")
self.lot_pk = kwargs.pop("lot_pk")
self.devices = kwargs.pop("devices", [])
super().__init__(*args, **kwargs)
def clean(self):
self._beneficiary = self.cleaned_data.get("beneficiary")
return self._beneficiary
def save(self, commit=True):
if not commit:
return
Beneficiary.objects.create(
email=self._beneficiary,
lot_id=self.lot_pk,
shop=self.shop
)
for dev in self.devices:
for ben in self._beneficiary:
ben.add(dev.id)
return
def remove(self):
for dev in self.devices:
for ben in self._beneficiary:
ben.remove(dev.id)
return
class LotSubscriptionForm(forms.Form):
user = forms.CharField()
type = forms.ChoiceField(

View file

@ -0,0 +1,72 @@
# Generated by Django 5.0.6 on 2025-03-13 11:57
import django.db.models.deletion
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("lot", "0009_donor_lotsubscription_and_more"),
]
operations = [
migrations.CreateModel(
name="Beneficiary",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"sign_conditions",
models.BooleanField(default=False, verbose_name="Conditions"),
),
(
"email",
models.EmailField(max_length=255, verbose_name="Email address"),
),
(
"lot",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="lot.lot"
),
),
(
"shop",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="lot.lotsubscription",
),
),
],
),
migrations.CreateModel(
name="DeviceBeneficiary",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("device_id", models.CharField(max_length=256)),
(
"beneficiary",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="lot.beneficiary",
),
),
],
),
]

View file

@ -95,3 +95,19 @@ class Donor(models.Model):
_('Email address'),
max_length=255,
)
class Beneficiary(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
sign_conditions = models.BooleanField(_("Conditions"), default=False)
lot = models.ForeignKey(Lot, on_delete=models.CASCADE)
shop = models.ForeignKey(LotSubscription, on_delete=models.CASCADE)
email = models.EmailField(
_('Email address'),
max_length=255,
)
class DeviceBeneficiary(models.Model):
beneficiary = models.ForeignKey("Beneficiary", on_delete=models.CASCADE)
device_id = models.CharField(max_length=STR_EXTEND_SIZE, blank=False, null=False)

View file

@ -0,0 +1,73 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<div class="row">
<div class="col">
<h3>{{ subtitle }}</h3>
</div>
</div>
{% if beneficiaries %}
<div class="row">
<div class="col">
<table class="table table-hover table-bordered align-middel">
<thead class="table-light">
<tr>
<th scope="col">{% trans 'Beneficiary' %}</th>
<th scope="col">{% trans 'Shop' %}</th>
<th scope="col">{% trans 'Sign conditions' %}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for s in beneficiaries %}
<tr>
<td class="font-monospace">{{ s.email }}</td>
<td class="font-monospace">{{ s.shop.user.email }}</td>
<td class="font-monospace">{{ s.sign_conditions }}</td>
<td class="font-monospace">
<a href="{# url 'lot:unsubscription' lot.id s.id #}">
{% trans 'Delete' %}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
<div class="mt-4">
<button class="btn btn-green-admin" type="button" data-bs-toggle="collapse" data-bs-target="#add_beneficiarie">
{% trans 'Add Beneficiarie' %}
</button>
<div class="collapse mt-3" id="add_beneficiarie">
<div class="card card-body">
{% trans 'Add an email of beneficiary' %}.
</div>
{% load django_bootstrap5 %}
<form role="form" method="post">
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-danger alert-icon alert-icon-border alert-dismissible" role="alert">
<div class="icon"><span class="mdi mdi-close-circle-o"></span></div>
<div class="message">
{% for field, error in form.errors.items %}
{{ error }}<br />
{% endfor %}
<button class="btn-close" type="button" data-dismiss="alert" aria-label="Close"></button>
</div>
</div>
{% endif %}
{% bootstrap_form form %}
<div class="form-actions-no-box">
<a class="btn btn-grey" href="{% url 'dashboard:lot' lot.id %}">{% translate "Cancel" %}</a>
<input class="btn btn-green-admin" type="submit" name="submit" value="{{ action }}" />
</div>
</form>
</div>
</div>
{% endblock %}

View file

@ -20,4 +20,5 @@ urlpatterns = [
path("<int:pk>/donor/del", views.DelDonorView.as_view(), name="del_donor"),
path("<int:pk>/donor/<uuid:id>", views.DonorView.as_view(), name="web_donor"),
path("<int:pk>/donor/<uuid:id>/accept", views.AcceptDonorView.as_view(), name="accept_donor"),
path("<int:pk>/beneficiary", views.BeneficiaryView.as_view(), name="beneficiary"),
]

View file

@ -13,8 +13,16 @@ from django.views.generic.edit import (
from dashboard.mixins import DashboardView
from evidence.models import SystemProperty
from device.models import Device
from lot.models import Lot, LotTag, LotProperty, LotSubscription, Donor
from lot.forms import LotsForm, LotSubscriptionForm, AddDonorForm
from lot.forms import LotsForm, LotSubscriptionForm, AddDonorForm, BeneficiaryForm
from lot.models import (
Lot,
LotTag,
LotProperty,
LotSubscription,
Beneficiary,
Donor
)
class NewLotView(DashboardView, CreateView):
template_name = "new_lot.html"
@ -289,9 +297,11 @@ class SubscriptLotView(DashboardView, FormView):
self.pk = self.kwargs.get('pk')
context = super().get_context_data(**kwargs)
self.get_lot()
subscriptors = []
if self.request.user.is_admin:
subscriptors = LotSubscription.objects.filter(lot=self.lot)
subscriptors = LotSubscription.objects.filter(lot=self.lot)
user_subscripted = subscriptors.filter(user=self.request.user).first()
if not self.request.user.is_admin and not user_subscripted:
subscriptors = []
context.update({
'lot': self.lot,
@ -486,3 +496,59 @@ class AcceptDonorView(TemplateView):
# self.send_email()
return redirect(self.success_url)
class BeneficiaryView(DashboardView, FormView):
template_name = "beneficiaries.html"
title = _("Beneficiaries")
breadcrumb = "Lot / Beneficiary"
form_class = BeneficiaryForm
lot = None
def get_context_data(self, **kwargs):
self.pk = self.kwargs.get('pk')
context = super().get_context_data(**kwargs)
self.get_lot()
self.is_shop = LotSubscription.objects.filter(
lot=self.lot,
user=self.request.user,
type=LotSubscription.Type.SHOP
).first()
beneficiaries = []
if self.request.user.is_admin or self.is_shop:
beneficiaries = Beneficiary.objects.filter(lot=self.lot)
context.update({
'lot': self.lot,
'beneficiaries': beneficiaries,
"action": _("Add")
})
return context
def get_form_kwargs(self):
self.pk = self.kwargs.get('pk')
self.success_url = reverse_lazy('dashboard:lot', args=[self.pk])
self.is_shop = LotSubscription.objects.filter(
lot_id=self.pk,
user=self.request.user,
type=LotSubscription.Type.SHOP
).first()
kwargs = super().get_form_kwargs()
kwargs["shop"] = self.is_shop
kwargs["lot_pk"] = self.pk
return kwargs
def get_lot(self):
self.lot = get_object_or_404(
Lot,
owner=self.request.user.institution,
id=self.pk
)
def form_valid(self, form):
form.save()
response = super().form_valid(form)
return response