mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 09:12:11 +01:00 
			
		
		
		
	Compare commits
	
		
			12 Commits
		
	
	
		
			0962a3735e
			...
			small_feat
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					516986f200 | ||
| 
						 | 
					206a967827 | ||
| 
						 | 
					69aedccbae | ||
| 
						 | 
					75a59e0a7a | ||
| 
						 | 
					af39bf7068 | ||
| 
						 | 
					7c45b59298 | ||
| 
						 | 
					22d668a75c | ||
| 
						 | 
					5dfa12fad2 | ||
| 
						 | 
					5af69f719d | ||
| 
						 | 
					4f6b1d5b6c | ||
| 
						 | 
					27a1f36183 | ||
| 
						 | 
					83c8b9a3d0 | 
@@ -37,6 +37,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
    <div id="guests_table">
 | 
			
		||||
        {% render_table guests %}
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="card-footer text-center">
 | 
			
		||||
        <button class="btn btn-block btn-primary mb-3" onclick="window.location.href='?_export=1&table=guests'">
 | 
			
		||||
            {% trans "Export to CSV" %}
 | 
			
		||||
        </button>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -136,20 +136,74 @@ class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMix
 | 
			
		||||
    model = Activity
 | 
			
		||||
    context_object_name = "activity"
 | 
			
		||||
    extra_context = {"title": _("Activity detail")}
 | 
			
		||||
    export_formats = ["csv"]
 | 
			
		||||
 | 
			
		||||
    tables = [
 | 
			
		||||
        lambda data: GuestTable(data, prefix="guests-"),
 | 
			
		||||
        lambda data: OpenerTable(data, prefix="opener-"),
 | 
			
		||||
        GuestTable,
 | 
			
		||||
        OpenerTable,
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    def get_tables(self):
 | 
			
		||||
        tables = super().get_tables()
 | 
			
		||||
        tables[0].prefix = "guests"
 | 
			
		||||
        tables[1].prefix = "opener"
 | 
			
		||||
        return tables
 | 
			
		||||
 | 
			
		||||
    def get_tables_data(self):
 | 
			
		||||
        return [
 | 
			
		||||
            Guest.objects.filter(activity=self.object)
 | 
			
		||||
                         .filter(PermissionBackend.filter_queryset(self.request, Guest, "view")),
 | 
			
		||||
                         .filter(PermissionBackend.filter_queryset(self.request, Guest, "view"))
 | 
			
		||||
                         .distinct(),
 | 
			
		||||
            self.object.opener.filter(activity=self.object)
 | 
			
		||||
                              .filter(PermissionBackend.filter_queryset(self.request, Opener, "view")),
 | 
			
		||||
                              .filter(PermissionBackend.filter_queryset(self.request, Opener, "view"))
 | 
			
		||||
                              .distinct(),
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
    def render_to_response(self, context, **response_kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Gère l'export CSV manuel pour MultiTableMixin.
 | 
			
		||||
        """
 | 
			
		||||
        if "_export" in self.request.GET:
 | 
			
		||||
            import tablib
 | 
			
		||||
            table_name = self.request.GET.get("table")
 | 
			
		||||
            if table_name:
 | 
			
		||||
                tables = self.get_tables()
 | 
			
		||||
                data_list = self.get_tables_data()
 | 
			
		||||
 | 
			
		||||
                for t, d in zip(tables, data_list):
 | 
			
		||||
                    if t.prefix == table_name:
 | 
			
		||||
                        # Préparer le CSV
 | 
			
		||||
                        dataset = tablib.Dataset()
 | 
			
		||||
                        columns = list(t.base_columns)  # noms des colonnes
 | 
			
		||||
                        dataset.headers = columns
 | 
			
		||||
 | 
			
		||||
                        for row in d:
 | 
			
		||||
                            values = []
 | 
			
		||||
                            for col in columns:
 | 
			
		||||
                                try:
 | 
			
		||||
                                    val = getattr(row, col, "")
 | 
			
		||||
                                    # Gestion spéciale pour la colonne 'entry'
 | 
			
		||||
                                    if col == "entry":
 | 
			
		||||
                                        if getattr(row, "has_entry", False):
 | 
			
		||||
                                            val = timezone.localtime(row.entry.time).strftime("%Y-%m-%d %H:%M:%S")
 | 
			
		||||
                                        else:
 | 
			
		||||
                                            val = ""
 | 
			
		||||
                                    values.append(str(val) if val is not None else "")
 | 
			
		||||
                                except Exception:  # RelatedObjectDoesNotExist ou autre
 | 
			
		||||
                                    values.append("")
 | 
			
		||||
                            dataset.append(values)
 | 
			
		||||
 | 
			
		||||
                        csv_bytes = dataset.export("csv")
 | 
			
		||||
                        if isinstance(csv_bytes, str):
 | 
			
		||||
                            csv_bytes = csv_bytes.encode("utf-8")
 | 
			
		||||
 | 
			
		||||
                        response = HttpResponse(csv_bytes, content_type="text/csv")
 | 
			
		||||
                        response["Content-Disposition"] = f'attachment; filename="{table_name}.csv"'
 | 
			
		||||
                        return response
 | 
			
		||||
 | 
			
		||||
        # Sinon rendu normal
 | 
			
		||||
        return super().render_to_response(context, **response_kwargs)
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data()
 | 
			
		||||
 | 
			
		||||
@@ -257,7 +311,7 @@ class ActivityInviteView(ProtectQuerysetMixin, ProtectedCreateView):
 | 
			
		||||
    @transaction.atomic
 | 
			
		||||
    def form_valid(self, form):
 | 
			
		||||
        form.instance.activity = Activity.objects\
 | 
			
		||||
            .filter(PermissionBackend.filter_queryset(self.request, Activity, "view")).get(pk=self.kwargs["pk"])
 | 
			
		||||
            .filter(PermissionBackend.filter_queryset(self.request, Activity, "view")).distinct().get(pk=self.kwargs["pk"])
 | 
			
		||||
        return super().form_valid(form)
 | 
			
		||||
 | 
			
		||||
    def get_success_url(self, **kwargs):
 | 
			
		||||
 
 | 
			
		||||
@@ -74,11 +74,15 @@ class FoodListView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMixin, Li
 | 
			
		||||
 | 
			
		||||
        search_table = qs.filter(PermissionBackend.filter_queryset(self.request, Food, 'view'))
 | 
			
		||||
        # table open
 | 
			
		||||
        open_table = self.get_queryset().order_by('expiry_date').filter(
 | 
			
		||||
        open_table = self.get_queryset().filter(
 | 
			
		||||
            Q(polymorphic_ctype__model='transformedfood')
 | 
			
		||||
            | Q(polymorphic_ctype__model='basicfood', basicfood__date_type='DLC')).filter(
 | 
			
		||||
                expiry_date__lt=timezone.now(), end_of_life='').filter(
 | 
			
		||||
                    PermissionBackend.filter_queryset(self.request, Food, 'view'))
 | 
			
		||||
        open_table = open_table.union(self.get_queryset().filter(
 | 
			
		||||
            Q(end_of_life='', order__iexact='open')
 | 
			
		||||
        ).filter(
 | 
			
		||||
            PermissionBackend.filter_queryset(self.request, Food, 'view'))).order_by('expiry_date')
 | 
			
		||||
        # table served
 | 
			
		||||
        served_table = self.get_queryset().order_by('-pk').filter(
 | 
			
		||||
            end_of_life='', is_ready=True).exclude(
 | 
			
		||||
 
 | 
			
		||||
@@ -417,7 +417,7 @@ class Membership(models.Model):
 | 
			
		||||
        A membership is valid if today is between the start and the end date.
 | 
			
		||||
        """
 | 
			
		||||
        if self.date_end is not None:
 | 
			
		||||
            return self.date_start.toordinal() <= datetime.datetime.now().toordinal() < self.date_end.toordinal()
 | 
			
		||||
            return self.date_start.toordinal() <= datetime.datetime.now().toordinal() <= self.date_end.toordinal()
 | 
			
		||||
        else:
 | 
			
		||||
            return self.date_start.toordinal() <= datetime.datetime.now().toordinal()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -92,6 +92,20 @@ class MembershipTable(tables.Table):
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    user_email = tables.Column(
 | 
			
		||||
        verbose_name="Email",
 | 
			
		||||
        accessor="user.email",
 | 
			
		||||
        orderable=False,
 | 
			
		||||
        visible=False,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    user_full_name = tables.Column(
 | 
			
		||||
        verbose_name=_("Full name"),
 | 
			
		||||
        accessor="user.get_full_name",
 | 
			
		||||
        orderable=False,
 | 
			
		||||
        visible=False,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def render_user(self, value):
 | 
			
		||||
        # If the user has the right, link the displayed user with the page of its detail.
 | 
			
		||||
        s = value.username
 | 
			
		||||
@@ -149,6 +163,16 @@ class MembershipTable(tables.Table):
 | 
			
		||||
                            + "'>" + s + "</a>")
 | 
			
		||||
        return s
 | 
			
		||||
 | 
			
		||||
    def value_user(self, record):
 | 
			
		||||
        return record.user.username if record.user else ""
 | 
			
		||||
 | 
			
		||||
    def value_club(self, record):
 | 
			
		||||
        return record.club.name if record.club else ""
 | 
			
		||||
 | 
			
		||||
    def value_roles(self, record):
 | 
			
		||||
        roles = record.roles.all()
 | 
			
		||||
        return ", ".join(str(role) for role in roles)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        attrs = {
 | 
			
		||||
            'class': 'table table-condensed table-striped',
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,13 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
            {% trans "There is no membership found with this pattern." %}
 | 
			
		||||
        </div>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        <div class="card-footer text-center">
 | 
			
		||||
            <button class="btn btn-block btn-primary mb-3" onclick="window.location.href='?_export=csv'">
 | 
			
		||||
                {% trans "Export to CSV" %}
 | 
			
		||||
            </button>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django.views.generic import DetailView, UpdateView, TemplateView
 | 
			
		||||
from django.views.generic.edit import FormMixin
 | 
			
		||||
from django_tables2.views import MultiTableMixin, SingleTableMixin, SingleTableView
 | 
			
		||||
from django_tables2.export.views import ExportMixin
 | 
			
		||||
from rest_framework.authtoken.models import Token
 | 
			
		||||
from api.viewsets import is_regex
 | 
			
		||||
from note.models import Alias, NoteClub, NoteUser, Trust
 | 
			
		||||
@@ -950,11 +951,12 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
 | 
			
		||||
        return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClubMembersListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
			
		||||
class ClubMembersListView(ExportMixin, ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
			
		||||
    model = Membership
 | 
			
		||||
    table_class = MembershipTable
 | 
			
		||||
    template_name = "member/club_members.html"
 | 
			
		||||
    extra_context = {"title": _("Members of the club")}
 | 
			
		||||
    export_formats = ["csv"]
 | 
			
		||||
 | 
			
		||||
    def get_queryset(self, **kwargs):
 | 
			
		||||
        qs = super().get_queryset().filter(club_id=self.kwargs["pk"])
 | 
			
		||||
@@ -986,6 +988,14 @@ class ClubMembersListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableV
 | 
			
		||||
 | 
			
		||||
        return qs.distinct()
 | 
			
		||||
 | 
			
		||||
    def get_export_filename(self, export_format):
 | 
			
		||||
        return "members.csv"
 | 
			
		||||
 | 
			
		||||
    def get_export_content_type(self, export_format):
 | 
			
		||||
        if export_format == "csv":
 | 
			
		||||
            return "text/csv"
 | 
			
		||||
        return super().get_export_content_type(export_format)
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        club = Club.objects.filter(
 | 
			
		||||
 
 | 
			
		||||
@@ -228,7 +228,7 @@ function consume (source, source_alias, dest, quantity, amount, reason, type, ca
 | 
			
		||||
          addMsg(interpolate(gettext('Warning, the transaction from the note %s succeed, ' +
 | 
			
		||||
              'but the emitter note %s is negative.'), [source_alias, source_alias]), 'warning', 30000)
 | 
			
		||||
        }
 | 
			
		||||
        if (source.membership && source.membership.date_end < new Date().toISOString()) {
 | 
			
		||||
        if (source.membership && source.membership.date_end <= new Date().toISOString()) {
 | 
			
		||||
          addMsg(interpolate(gettext('Warning, the emitter note %s is no more a BDE member.'), [source_alias]),
 | 
			
		||||
              'danger', 30000)
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -310,10 +310,10 @@ $('#btn_transfer').click(function () {
 | 
			
		||||
            destination: dest.note.id,
 | 
			
		||||
            destination_alias: dest.name
 | 
			
		||||
          }).done(function () {
 | 
			
		||||
          if (source.note.membership && source.note.membership.date_end < new Date().toISOString()) {
 | 
			
		||||
          if (source.note.membership && source.note.membership.date_end <= new Date().toISOString()) {
 | 
			
		||||
            addMsg(interpolate(gettext('Warning, the emitter note %s is no more a BDE member.'), [source.name]), 'danger', 30000)
 | 
			
		||||
          }
 | 
			
		||||
          if (dest.note.membership && dest.note.membership.date_end < new Date().toISOString()) {
 | 
			
		||||
          if (dest.note.membership && dest.note.membership.date_end <= new Date().toISOString()) {
 | 
			
		||||
            addMsg(interpolate(gettext('Warning, the destination note %s is no more a BDE member.'), [dest.name]), 'danger', 30000)
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
@@ -414,7 +414,7 @@ $('#btn_transfer').click(function () {
 | 
			
		||||
        bank: $('#bank').val()
 | 
			
		||||
      }).done(function () {
 | 
			
		||||
      addMsg(gettext('Credit/debit succeed!'), 'success', 10000)
 | 
			
		||||
      if (user_note.membership && user_note.membership.date_end < new Date().toISOString()) { addMsg(gettext('Warning, the emitter note %s is no more a BDE member.'), 'danger', 10000) }
 | 
			
		||||
      if (user_note.membership && user_note.membership.date_end <= new Date().toISOString()) { addMsg(gettext('Warning, the emitter note %s is no more a BDE member.'), 'danger', 10000) }
 | 
			
		||||
      reset()
 | 
			
		||||
    }).fail(function (err) {
 | 
			
		||||
      const errObj = JSON.parse(err.responseText)
 | 
			
		||||
 
 | 
			
		||||
@@ -927,7 +927,7 @@
 | 
			
		||||
                "note",
 | 
			
		||||
                "transactiontemplate"
 | 
			
		||||
            ],
 | 
			
		||||
            "query": "{\"destination\": [\"club\", \"note\"]}",
 | 
			
		||||
            "query": "[\"AND\", {\"destination\": [\"club\", \"note\"]}, {\"category__name\": \"Clubs\"}]",
 | 
			
		||||
            "type": "view",
 | 
			
		||||
            "mask": 2,
 | 
			
		||||
            "field": "",
 | 
			
		||||
@@ -943,7 +943,7 @@
 | 
			
		||||
                "note",
 | 
			
		||||
                "transactiontemplate"
 | 
			
		||||
            ],
 | 
			
		||||
            "query": "{\"destination\": [\"club\", \"note\"]}",
 | 
			
		||||
            "query": "[\"AND\", {\"destination\": [\"club\", \"note\"]}, {\"category__name\": \"Clubs\"}]", 
 | 
			
		||||
            "type": "add",
 | 
			
		||||
            "mask": 3,
 | 
			
		||||
            "field": "",
 | 
			
		||||
@@ -959,7 +959,7 @@
 | 
			
		||||
                "note",
 | 
			
		||||
                "transactiontemplate"
 | 
			
		||||
            ],
 | 
			
		||||
            "query": "{\"destination\": [\"club\", \"note\"]}",
 | 
			
		||||
            "query": "[\"AND\", {\"destination\": [\"club\", \"note\"]}, {\"category__name\": \"Clubs\"}]",
 | 
			
		||||
            "type": "change",
 | 
			
		||||
            "mask": 3,
 | 
			
		||||
            "field": "",
 | 
			
		||||
@@ -3484,7 +3484,23 @@
 | 
			
		||||
	    "mask": 1,
 | 
			
		||||
	    "permanent": false,
 | 
			
		||||
	    "description": "Voir la bouffe servie"
 | 
			
		||||
	}
 | 
			
		||||
	    }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "model": "permission.permission",
 | 
			
		||||
        "pk": 223,
 | 
			
		||||
        "fields": {
 | 
			
		||||
            "model": [
 | 
			
		||||
                "note",
 | 
			
		||||
                "templatecategory"
 | 
			
		||||
            ],
 | 
			
		||||
            "query": "{\"name\": \"Clubs\"}",
 | 
			
		||||
            "type": "view",
 | 
			
		||||
            "mask": 2,
 | 
			
		||||
            "field": "",
 | 
			
		||||
            "permanent": false,
 | 
			
		||||
            "description": "Voir la catégorie de bouton Clubs"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "model": "permission.permission",
 | 
			
		||||
@@ -4702,6 +4718,22 @@
 | 
			
		||||
            "description": "Supprimer un succès"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "model": "permission.permission",
 | 
			
		||||
        "pk": 330,
 | 
			
		||||
        "fields": {
 | 
			
		||||
            "model": [
 | 
			
		||||
                "auth",
 | 
			
		||||
                "user"
 | 
			
		||||
            ],
 | 
			
		||||
            "query": "{\"memberships__club\": [\"club\"]}",
 | 
			
		||||
            "type": "view",
 | 
			
		||||
            "mask": 2,
 | 
			
		||||
            "field": "email",
 | 
			
		||||
            "permanent": false,
 | 
			
		||||
            "description": "Voir l'adresse mail des membres de son club"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "model": "permission.role",
 | 
			
		||||
        "pk": 1,
 | 
			
		||||
@@ -4852,7 +4884,8 @@
 | 
			
		||||
                259,
 | 
			
		||||
                260,
 | 
			
		||||
                263,
 | 
			
		||||
                265
 | 
			
		||||
                265,
 | 
			
		||||
                330
 | 
			
		||||
            ]
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
@@ -4879,7 +4912,6 @@
 | 
			
		||||
                19,
 | 
			
		||||
                20,
 | 
			
		||||
                21,
 | 
			
		||||
                27,
 | 
			
		||||
                59,
 | 
			
		||||
                60,
 | 
			
		||||
                61,
 | 
			
		||||
@@ -4890,6 +4922,7 @@
 | 
			
		||||
                182,
 | 
			
		||||
                184,
 | 
			
		||||
                185,
 | 
			
		||||
                223,
 | 
			
		||||
                239,
 | 
			
		||||
                240,
 | 
			
		||||
                241
 | 
			
		||||
@@ -5201,6 +5234,7 @@
 | 
			
		||||
            "permissions": [
 | 
			
		||||
                37,
 | 
			
		||||
                41,
 | 
			
		||||
                42,
 | 
			
		||||
                53,
 | 
			
		||||
                54,
 | 
			
		||||
                55,
 | 
			
		||||
@@ -5253,6 +5287,12 @@
 | 
			
		||||
                176,
 | 
			
		||||
                177,
 | 
			
		||||
                197,
 | 
			
		||||
                211,
 | 
			
		||||
                212,
 | 
			
		||||
                213,
 | 
			
		||||
                214,
 | 
			
		||||
                215,
 | 
			
		||||
                216,
 | 
			
		||||
                311,
 | 
			
		||||
                319
 | 
			
		||||
            ]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								apps/treasury/migrations/0011_sogecredit_valid.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								apps/treasury/migrations/0011_sogecredit_valid.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 5.2.6 on 2025-09-28 20:12
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('treasury', '0010_alter_invoice_bde'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AddField(
 | 
			
		||||
            model_name='sogecredit',
 | 
			
		||||
            name='valid',
 | 
			
		||||
            field=models.BooleanField(blank=True, default=False, verbose_name='Valid'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -308,6 +308,12 @@ class SogeCredit(models.Model):
 | 
			
		||||
        null=True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    valid = models.BooleanField(
 | 
			
		||||
        default=False,
 | 
			
		||||
        verbose_name=_("Valid"),
 | 
			
		||||
        blank=True,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name = _("Credit from the Société générale")
 | 
			
		||||
        verbose_name_plural = _("Credits from the Société générale")
 | 
			
		||||
@@ -332,7 +338,7 @@ class SogeCredit(models.Model):
 | 
			
		||||
                last_name=self.user.last_name,
 | 
			
		||||
                first_name=self.user.first_name,
 | 
			
		||||
                bank="Société générale",
 | 
			
		||||
                valid=False,
 | 
			
		||||
                valid=True,
 | 
			
		||||
            )
 | 
			
		||||
            credit_transaction._force_save = True
 | 
			
		||||
            credit_transaction.save()
 | 
			
		||||
@@ -346,12 +352,12 @@ class SogeCredit(models.Model):
 | 
			
		||||
        return super().save(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def valid(self):
 | 
			
		||||
    def valid_legacy(self):
 | 
			
		||||
        return self.credit_transaction and self.credit_transaction.valid
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def amount(self):
 | 
			
		||||
        if self.valid:
 | 
			
		||||
        if self.valid_legacy:
 | 
			
		||||
            return self.credit_transaction.total
 | 
			
		||||
        amount = 0
 | 
			
		||||
        transactions_wei = self.transactions.filter(membership__club__weiclub__isnull=False)
 | 
			
		||||
@@ -397,7 +403,7 @@ class SogeCredit(models.Model):
 | 
			
		||||
                        self.transactions.add(m.transaction)
 | 
			
		||||
 | 
			
		||||
        for tr in self.transactions.all():
 | 
			
		||||
            tr.valid = False
 | 
			
		||||
            tr.valid = True
 | 
			
		||||
            tr.save()
 | 
			
		||||
 | 
			
		||||
    def invalidate(self):
 | 
			
		||||
@@ -422,6 +428,7 @@ class SogeCredit(models.Model):
 | 
			
		||||
        self.invalidate()
 | 
			
		||||
        # Refresh credit amount
 | 
			
		||||
        self.save()
 | 
			
		||||
        self.valid = True
 | 
			
		||||
        self.credit_transaction.valid = True
 | 
			
		||||
        self.credit_transaction._force_save = True
 | 
			
		||||
        self.credit_transaction.save()
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,7 @@ class InvoiceTable(tables.Table):
 | 
			
		||||
        model = Invoice
 | 
			
		||||
        template_name = 'django_tables2/bootstrap4.html'
 | 
			
		||||
        fields = ('id', 'name', 'object', 'acquitted', 'invoice',)
 | 
			
		||||
        order_by = ('-id',)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemittanceTable(tables.Table):
 | 
			
		||||
 
 | 
			
		||||
@@ -108,7 +108,7 @@
 | 
			
		||||
 | 
			
		||||
\renewcommand{\headrulewidth}{0pt}
 | 
			
		||||
\cfoot{
 | 
			
		||||
    \small{\MonNom  ~--~ \MonAdresseRue ~ \MonAdresseVille ~--~ Téléphone : +33(0)7 78 17 22 34\newline
 | 
			
		||||
    \small{\MonNom  ~--~ \MonAdresseRue ~ \MonAdresseVille ~--~ Téléphone : +33(0)6 83 55 03 18 \newline
 | 
			
		||||
     E-mail : tresorerie.bde@lists.crans.org ~--~ Numéro SIRET : 399 485 838 00029
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -417,7 +417,7 @@ class SogeCreditListView(LoginRequiredMixin, ProtectQuerysetMixin, SingleTableVi
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
        if "valid" not in self.request.GET or not self.request.GET["valid"]:
 | 
			
		||||
            qs = qs.filter(credit_transaction__valid=False)
 | 
			
		||||
            qs = qs.filter(valid=False)
 | 
			
		||||
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -680,7 +680,7 @@ class TestWEIRegistration(TestCase):
 | 
			
		||||
            self.assertTrue(soge_credit.exists())
 | 
			
		||||
            soge_credit = soge_credit.get()
 | 
			
		||||
            self.assertTrue(membership.transaction in soge_credit.transactions.all())
 | 
			
		||||
            self.assertFalse(membership.transaction.valid)
 | 
			
		||||
            self.assertTrue(membership.transaction.valid)
 | 
			
		||||
 | 
			
		||||
        # Check that if the WEI is started, we can't update a wei
 | 
			
		||||
        self.wei.date_start = date(2000, 1, 1)
 | 
			
		||||
 
 | 
			
		||||
@@ -12,10 +12,11 @@ django-filter~=25.1
 | 
			
		||||
django-mailer~=2.3.2
 | 
			
		||||
django-oauth-toolkit~=3.0.1
 | 
			
		||||
django-phonenumber-field~=8.1.0
 | 
			
		||||
django-polymorphic~=3.1.0
 | 
			
		||||
django-polymorphic~=4.1.0
 | 
			
		||||
djangorestframework~=3.16.0
 | 
			
		||||
django-rest-polymorphic~=0.1.10
 | 
			
		||||
django-tables2~=2.7.5
 | 
			
		||||
python-memcached~=1.62
 | 
			
		||||
phonenumbers~=9.0.8
 | 
			
		||||
tablib~=3.8.0
 | 
			
		||||
Pillow>=11.3.0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user