mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-11-04 01:12:08 +01:00 
			
		
		
		
	Compare commits
	
		
			43 Commits
		
	
	
		
			qrcode
			...
			fix_pipeli
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					81c12436a8 | ||
| 
						 | 
					8eee14075c | ||
| 
						 | 
					ab9ba62af1 | ||
| 
						 | 
					8ca0648e75 | ||
| 
						 | 
					77ecfd6ed5 | ||
| 
						 | 
					0ab1367e55 | ||
| 
						 | 
					524f0e098a | ||
| 
						 | 
					1ca4246cbd | ||
| 
						 | 
					6a9021ec14 | ||
| 
						 | 
					cb74311e7b | ||
| 
						 | 
					9d7dd566c9 | ||
| 
						 | 
					9944ebcaad | ||
| 
						 | 
					8537f043f7 | ||
| 
						 | 
					c89a95f8d2 | ||
| 
						 | 
					73640b1dfa | ||
| 
						 | 
					84b16ab603 | ||
| 
						 | 
					6a1b51dbbf | ||
| 
						 | 
					c441a43a8b | ||
| 
						 | 
					87f3b51b04 | ||
| 
						 | 
					0a853fd3e6 | ||
| 
						 | 
					c429734810 | ||
| 
						 | 
					5d759111b6 | ||
| 
						 | 
					70baf7566c | ||
| 
						 | 
					eb355f547c | ||
| 
						 | 
					7068170f18 | ||
| 
						 | 
					45ee9a8941 | ||
| 
						 | 
					454ea19603 | ||
| 5a77a66391 | |||
| 
						 | 
					
						
						
							
						
						761fc170eb
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						ac23d7eb54
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						40e7415062
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						319405d2b1
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						633ab88b04
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						e29b42eecc
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						dc69faaf1d
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						442a5c5e36
	
				 | 
					
					
						||
| 
						 | 
					
						
						
							
						
						7ab0fec3bc
	
				 | 
					
					
						||
| 
						 | 
					bd4fb23351 | ||
| 
						 | 
					ee22e9b3b6 | ||
| 
						 | 
					19ae616fb4 | ||
| 
						 | 
					b7657ec362 | ||
| 
						 | 
					4d03d9460d | ||
| 3633f66a87 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -42,6 +42,7 @@ map.json
 | 
			
		||||
backups/
 | 
			
		||||
/static/
 | 
			
		||||
/media/
 | 
			
		||||
/tmp/
 | 
			
		||||
 | 
			
		||||
# Virtualenv
 | 
			
		||||
env/
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
</a>
 | 
			
		||||
 | 
			
		||||
<input id="alias" type="text" class="form-control" placeholder="Nom/note ...">
 | 
			
		||||
<button id="trigger" class="btn btn-secondary">Click me !</button>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
@@ -64,46 +63,15 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
        refreshBalance();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function process_qrcode() {
 | 
			
		||||
        let name = alias_obj.val();
 | 
			
		||||
        $.get("/api/note/note?search=" + name + "&format=json").done(
 | 
			
		||||
            function (res) {
 | 
			
		||||
                let note = res.results[0];
 | 
			
		||||
                $.post("/api/activity/entry/?format=json", {
 | 
			
		||||
                    csrfmiddlewaretoken: CSRF_TOKEN,
 | 
			
		||||
                    activity: {{ activity.id }},
 | 
			
		||||
                    note: note.id,
 | 
			
		||||
                    guest: null
 | 
			
		||||
                }).done(function () {
 | 
			
		||||
                    addMsg(interpolate(gettext(
 | 
			
		||||
                        "Entry made for %s whose balance is %s €"),
 | 
			
		||||
                        [note.name, note.balance / 100]), "success", 4000);
 | 
			
		||||
                    reloadTable(true);
 | 
			
		||||
                }).fail(function (xhr) {
 | 
			
		||||
                    errMsg(xhr.responseJSON, 4000);
 | 
			
		||||
                });
 | 
			
		||||
            }).fail(function (xhr) {
 | 
			
		||||
                errMsg(xhr.responseJSON, 4000);
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    alias_obj.keyup(function(event) {
 | 
			
		||||
        let code = event.originalEvent.keyCode
 | 
			
		||||
        if (65 <= code <= 122 || code === 13) {
 | 
			
		||||
            debounce(reloadTable)()
 | 
			
		||||
        }
 | 
			
		||||
        if (code === 0)
 | 
			
		||||
            process_qrcode();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $(document).ready(init);
 | 
			
		||||
 | 
			
		||||
    alias_obj2 = document.getElementById("alias");
 | 
			
		||||
    $("#trigger").click(function (e) {
 | 
			
		||||
        addMsg("Clicked", "success", 1000);
 | 
			
		||||
        alias_obj.val(alias_obj.val() + "\0");
 | 
			
		||||
        alias_obj2.dispatchEvent(new KeyboardEvent('keyup'));
 | 
			
		||||
    })
 | 
			
		||||
    function init() {
 | 
			
		||||
        $(".table-row").click(function (e) {
 | 
			
		||||
            let target = e.target.parentElement;
 | 
			
		||||
@@ -200,4 +168,4 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
							
								
								
									
										5
									
								
								apps/api/pagination.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								apps/api/pagination.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
from rest_framework.pagination import PageNumberPagination
 | 
			
		||||
 | 
			
		||||
class CustomPagination(PageNumberPagination):
 | 
			
		||||
    page_size_query_param = 'page_size'
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								apps/member/migrations/0009_auto_20220904_2325.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								apps/member/migrations/0009_auto_20220904_2325.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2.26 on 2022-09-04 21:25
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('member', '0008_auto_20211005_1544'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='profile',
 | 
			
		||||
            name='promotion',
 | 
			
		||||
            field=models.PositiveSmallIntegerField(default=2022, help_text='Year of entry to the school (None if not ENS student)', null=True, verbose_name='promotion'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										53
									
								
								apps/member/static/member/js/trust.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								apps/member/static/member/js/trust.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
/**
 | 
			
		||||
 * On form submit, create a new friendship
 | 
			
		||||
 */
 | 
			
		||||
function create_trust (e) {
 | 
			
		||||
  // Do not submit HTML form
 | 
			
		||||
  e.preventDefault()
 | 
			
		||||
 | 
			
		||||
  // Get data and send to API
 | 
			
		||||
  const formData = new FormData(e.target)
 | 
			
		||||
  $.getJSON('/api/note/alias/'+formData.get('trusted') + '/',
 | 
			
		||||
    function (trusted_alias) {
 | 
			
		||||
      if ((trusted_alias.note == formData.get('trusting')))
 | 
			
		||||
      {
 | 
			
		||||
         addMsg(gettext("You can't add yourself as a friend"), "danger")
 | 
			
		||||
         return
 | 
			
		||||
      }
 | 
			
		||||
      $.post('/api/note/trust/', {
 | 
			
		||||
        csrfmiddlewaretoken: formData.get('csrfmiddlewaretoken'),
 | 
			
		||||
        trusting: formData.get('trusting'),
 | 
			
		||||
        trusted: trusted_alias.note
 | 
			
		||||
      }).done(function () {
 | 
			
		||||
        // Reload table
 | 
			
		||||
        $('#trust_table').load(location.pathname + ' #trust_table')
 | 
			
		||||
        addMsg(gettext('Friendship successfully added'), 'success')
 | 
			
		||||
      }).fail(function (xhr, _textStatus, _error) {
 | 
			
		||||
        errMsg(xhr.responseJSON)
 | 
			
		||||
      })
 | 
			
		||||
    }).fail(function (xhr, _textStatus, _error) {
 | 
			
		||||
        errMsg(xhr.responseJSON)
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * On click of "delete", delete the alias
 | 
			
		||||
 * @param button_id:Integer Alias id to remove
 | 
			
		||||
 */
 | 
			
		||||
function delete_button (button_id) {
 | 
			
		||||
  $.ajax({
 | 
			
		||||
    url: '/api/note/trust/' + button_id + '/',
 | 
			
		||||
    method: 'DELETE',
 | 
			
		||||
    headers: { 'X-CSRFTOKEN': CSRF_TOKEN }
 | 
			
		||||
  }).done(function () {
 | 
			
		||||
    addMsg(gettext('Friendship successfully deleted'), 'success')
 | 
			
		||||
    $('#trust_table').load(location.pathname + ' #trust_table')
 | 
			
		||||
  }).fail(function (xhr, _textStatus, _error) {
 | 
			
		||||
    errMsg(xhr.responseJSON)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
$(document).ready(function () {
 | 
			
		||||
  // Attach event
 | 
			
		||||
  document.getElementById('form_trust').addEventListener('submit', create_trust)
 | 
			
		||||
})
 | 
			
		||||
@@ -25,6 +25,14 @@
 | 
			
		||||
        </a>
 | 
			
		||||
    </dd>
 | 
			
		||||
 | 
			
		||||
    <dt class="col-xl-6">{% trans 'friendships'|capfirst %}</dt>
 | 
			
		||||
    <dd class="col-xl-6">
 | 
			
		||||
        <a class="badge badge-secondary" href="{% url 'member:user_trust' user_object.pk %}">
 | 
			
		||||
            <i class="fa fa-edit"></i>
 | 
			
		||||
            {% trans 'Manage friendships' %} ({{ user_object.note.trusting.all|length }})
 | 
			
		||||
        </a>
 | 
			
		||||
    </dd>
 | 
			
		||||
 | 
			
		||||
    {% if "member.view_profile"|has_perm:user_object.profile %}
 | 
			
		||||
        <dt class="col-xl-6">{% trans 'section'|capfirst %}</dt>
 | 
			
		||||
        <dd class="col-xl-6">{{ user_object.profile.section }}</dd>
 | 
			
		||||
@@ -52,10 +60,7 @@
 | 
			
		||||
{% if user_object.pk == user.pk %}
 | 
			
		||||
    <div class="text-center">
 | 
			
		||||
        <a class="small badge badge-secondary" href="{% url 'member:auth_token' %}">
 | 
			
		||||
            <i class="fa fa-cogs"></i> {% trans 'API token' %}
 | 
			
		||||
        </a>
 | 
			
		||||
        <a class="small badge badge-secondary" href="{% url 'member:qr_code' user_object.pk %}">
 | 
			
		||||
            <i class="fa fa-qrcode"></i> {% trans 'QR Code' %}
 | 
			
		||||
            <i class="fa fa-cogs"></i>{% trans 'API token' %}
 | 
			
		||||
        </a>
 | 
			
		||||
    </div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								apps/member/templates/member/profile_trust.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								apps/member/templates/member/profile_trust.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
{% extends "member/base.html" %}
 | 
			
		||||
{% comment %}
 | 
			
		||||
SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
{% load static django_tables2 i18n %}
 | 
			
		||||
 | 
			
		||||
{% block profile_content %}
 | 
			
		||||
<div class="card bg-light mb-3">
 | 
			
		||||
    <h3 class="card-header text-center">
 | 
			
		||||
        {% trans "Note friendships" %}
 | 
			
		||||
    </h3>
 | 
			
		||||
    <div class="card-body">
 | 
			
		||||
        {% if can_create %}
 | 
			
		||||
            <form class="input-group" method="POST" id="form_trust">
 | 
			
		||||
                {% csrf_token %}
 | 
			
		||||
                <input type="hidden" name="trusting" value="{{ object.note.pk }}">
 | 
			
		||||
                {%include "autocomplete_model.html" %}
 | 
			
		||||
                <div class="input-group-append">
 | 
			
		||||
                    <input type="submit" class="btn btn-success" value="{% trans "Add" %}">
 | 
			
		||||
                </div>
 | 
			
		||||
            </form>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
    </div>
 | 
			
		||||
    {% render_table trusting %}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="alert alert-warning card">
 | 
			
		||||
    {% blocktrans trimmed %}
 | 
			
		||||
        Adding someone as a friend enables them to initiate transactions coming
 | 
			
		||||
        from your account (while keeping your balance positive). This is
 | 
			
		||||
        designed to simplify using note kfet transfers to transfer money between
 | 
			
		||||
        users. The intent is that one person can make all transfers for a group of
 | 
			
		||||
        friends without needing additional rights among them.
 | 
			
		||||
    {% endblocktrans %}
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block extrajavascript %}
 | 
			
		||||
<script src="{% static "member/js/trust.js" %}"></script>
 | 
			
		||||
<script src="{% static "js/autocomplete_model.js" %}"></script>
 | 
			
		||||
{% endblock%}
 | 
			
		||||
@@ -1,36 +0,0 @@
 | 
			
		||||
{% extends "base.html" %}
 | 
			
		||||
{% comment %}
 | 
			
		||||
SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
<div class="card bg-light">
 | 
			
		||||
  	<h3 class="card-header text-center">
 | 
			
		||||
		{% trans "QR Code for" %} {{ user_object.username }} ({{ user_object.first_name }} {{user_object.last_name }})
 | 
			
		||||
  	</h3>
 | 
			
		||||
  	<div class="text-center" id="qrcode">
 | 
			
		||||
  	</div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block extrajavascript %}
 | 
			
		||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js" integrity="sha512-CNgIRecGo7nphbeZ04Sc13ka07paqdeTu0WR1IM4kNcpmBAUSHSQX0FslNhTDadL4O5SAGapGt4FodqL8My0mA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
 | 
			
		||||
<script>
 | 
			
		||||
	var qrc = new QRCode(document.getElementById("qrcode"), {
 | 
			
		||||
		text: "{{ user_object.pk }}\0",
 | 
			
		||||
		width: 1024,
 | 
			
		||||
		height: 1024
 | 
			
		||||
	});
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block extracss %}
 | 
			
		||||
<style>
 | 
			
		||||
img {
 | 
			
		||||
    width: 100%
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -23,6 +23,6 @@ urlpatterns = [
 | 
			
		||||
    path('user/<int:pk>/update/', views.UserUpdateView.as_view(), name="user_update_profile"),
 | 
			
		||||
    path('user/<int:pk>/update_pic/', views.ProfilePictureUpdateView.as_view(), name="user_update_pic"),
 | 
			
		||||
    path('user/<int:pk>/aliases/', views.ProfileAliasView.as_view(), name="user_alias"),
 | 
			
		||||
    path('user/<int:pk>/trust', views.ProfileTrustView.as_view(), name="user_trust"),
 | 
			
		||||
    path('manage-auth-token/', views.ManageAuthTokens.as_view(), name='auth_token'),
 | 
			
		||||
    path('user/<int:pk>/qr_code/', views.QRCodeView.as_view(), name='qr_code'),
 | 
			
		||||
]
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ from django.contrib.auth import logout
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from django.contrib.auth.views import LoginView
 | 
			
		||||
from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.db.models import Q, F
 | 
			
		||||
from django.shortcuts import redirect
 | 
			
		||||
@@ -18,9 +19,9 @@ from django.views.generic import DetailView, UpdateView, TemplateView
 | 
			
		||||
from django.views.generic.edit import FormMixin
 | 
			
		||||
from django_tables2.views import SingleTableView
 | 
			
		||||
from rest_framework.authtoken.models import Token
 | 
			
		||||
from note.models import Alias, NoteUser, NoteClub
 | 
			
		||||
from note.models import Alias, NoteClub, NoteUser, Trust
 | 
			
		||||
from note.models.transactions import Transaction, SpecialTransaction
 | 
			
		||||
from note.tables import HistoryTable, AliasTable
 | 
			
		||||
from note.tables import HistoryTable, AliasTable, TrustTable
 | 
			
		||||
from note_kfet.middlewares import _set_current_request
 | 
			
		||||
from permission.backends import PermissionBackend
 | 
			
		||||
from permission.models import Role
 | 
			
		||||
@@ -243,6 +244,39 @@ class UserListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProfileTrustView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
 | 
			
		||||
    """
 | 
			
		||||
    View and manage user trust relationships
 | 
			
		||||
    """
 | 
			
		||||
    model = User
 | 
			
		||||
    template_name = 'member/profile_trust.html'
 | 
			
		||||
    context_object_name = 'user_object'
 | 
			
		||||
    extra_context = {"title": _("Note friendships")}
 | 
			
		||||
 | 
			
		||||
    def get_context_data(self, **kwargs):
 | 
			
		||||
        context = super().get_context_data(**kwargs)
 | 
			
		||||
        note = context['object'].note
 | 
			
		||||
        context["trusting"] = TrustTable(
 | 
			
		||||
            note.trusting.filter(PermissionBackend.filter_queryset(self.request, Trust, "view")).distinct().all())
 | 
			
		||||
        context["can_create"] = PermissionBackend.check_perm(self.request, "note.add_trust", Trust(
 | 
			
		||||
            trusting=context["object"].note,
 | 
			
		||||
            trusted=context["object"].note
 | 
			
		||||
        ))
 | 
			
		||||
        context["widget"] = {
 | 
			
		||||
            "name": "trusted",
 | 
			
		||||
            "attrs": {
 | 
			
		||||
                "model_pk": ContentType.objects.get_for_model(Alias).pk,
 | 
			
		||||
                "class": "autocomplete form-control",
 | 
			
		||||
                "id": "trusted",
 | 
			
		||||
                "resetable": True,
 | 
			
		||||
                "api_url": "/api/note/alias/?note__polymorphic_ctype__model=noteuser",
 | 
			
		||||
                "name_field": "name",
 | 
			
		||||
                "placeholder": ""
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ProfileAliasView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
 | 
			
		||||
    """
 | 
			
		||||
    View and manage user aliases.
 | 
			
		||||
@@ -331,14 +365,6 @@ class ManageAuthTokens(LoginRequiredMixin, TemplateView):
 | 
			
		||||
        context['token'] = Token.objects.get_or_create(user=self.request.user)[0]
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
class QRCodeView(LoginRequiredMixin, DetailView):
 | 
			
		||||
    """
 | 
			
		||||
    Affiche le QR Code
 | 
			
		||||
    """
 | 
			
		||||
    model = User
 | 
			
		||||
    context_object_name = "user_object"
 | 
			
		||||
    template_name = "member/qr_code.html"
 | 
			
		||||
    extra_context = {"title": _("QR Code")}
 | 
			
		||||
 | 
			
		||||
# ******************************* #
 | 
			
		||||
#              CLUB               #
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ from note_kfet.middlewares import get_current_request
 | 
			
		||||
from permission.backends import PermissionBackend
 | 
			
		||||
from rest_framework.utils import model_meta
 | 
			
		||||
 | 
			
		||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
 | 
			
		||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias, Trust
 | 
			
		||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
 | 
			
		||||
    RecurrentTransaction, SpecialTransaction
 | 
			
		||||
 | 
			
		||||
@@ -77,6 +77,22 @@ class NoteUserSerializer(serializers.ModelSerializer):
 | 
			
		||||
        return str(obj)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TrustSerializer(serializers.ModelSerializer):
 | 
			
		||||
    """
 | 
			
		||||
    REST API Serializer for Trusts.
 | 
			
		||||
    The djangorestframework plugin will analyse the model `Trust` and parse all fields in the API.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        model = Trust
 | 
			
		||||
        fields = '__all__'
 | 
			
		||||
 | 
			
		||||
    def validate(self, attrs):
 | 
			
		||||
        instance = Trust(**attrs)
 | 
			
		||||
        instance.clean()
 | 
			
		||||
        return attrs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AliasSerializer(serializers.ModelSerializer):
 | 
			
		||||
    """
 | 
			
		||||
    REST API Serializer for Aliases.
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,8 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from .views import NotePolymorphicViewSet, AliasViewSet, ConsumerViewSet, \
 | 
			
		||||
    TemplateCategoryViewSet, TransactionViewSet, TransactionTemplateViewSet
 | 
			
		||||
    TemplateCategoryViewSet, TransactionViewSet, TransactionTemplateViewSet, \
 | 
			
		||||
    TrustViewSet
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def register_note_urls(router, path):
 | 
			
		||||
@@ -11,6 +12,7 @@ def register_note_urls(router, path):
 | 
			
		||||
    """
 | 
			
		||||
    router.register(path + '/note', NotePolymorphicViewSet)
 | 
			
		||||
    router.register(path + '/alias', AliasViewSet)
 | 
			
		||||
    router.register(path + '/trust', TrustViewSet)
 | 
			
		||||
    router.register(path + '/consumer', ConsumerViewSet)
 | 
			
		||||
 | 
			
		||||
    router.register(path + '/transaction/category', TemplateCategoryViewSet)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,9 @@ from api.viewsets import ReadProtectedModelViewSet, ReadOnlyProtectedModelViewSe
 | 
			
		||||
from permission.backends import PermissionBackend
 | 
			
		||||
 | 
			
		||||
from .serializers import NotePolymorphicSerializer, AliasSerializer, ConsumerSerializer,\
 | 
			
		||||
    TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer
 | 
			
		||||
from ..models.notes import Note, Alias, NoteUser, NoteClub, NoteSpecial
 | 
			
		||||
    TemplateCategorySerializer, TransactionTemplateSerializer, TransactionPolymorphicSerializer, \
 | 
			
		||||
    TrustSerializer
 | 
			
		||||
from ..models.notes import Note, Alias, NoteUser, NoteClub, NoteSpecial, Trust
 | 
			
		||||
from ..models.transactions import TransactionTemplate, Transaction, TemplateCategory
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -56,11 +57,41 @@ class NotePolymorphicViewSet(ReadProtectedModelViewSet):
 | 
			
		||||
        return queryset.order_by("id")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TrustViewSet(ReadProtectedModelViewSet):
 | 
			
		||||
    """
 | 
			
		||||
    REST Trust View set.
 | 
			
		||||
    The djangorestframework plugin will get all `Trust` objects, serialize it to JSON with the given serializer,
 | 
			
		||||
    then render it on /api/note/trust/
 | 
			
		||||
    """
 | 
			
		||||
    queryset = Trust.objects
 | 
			
		||||
    serializer_class = TrustSerializer
 | 
			
		||||
    filter_backends = [SearchFilter, DjangoFilterBackend, OrderingFilter]
 | 
			
		||||
    search_fields = ['$trusting__alias__name', '$trusting__alias__normalized_name',
 | 
			
		||||
                     '$trusted__alias__name', '$trusted__alias__normalized_name']
 | 
			
		||||
    filterset_fields = ['trusting', 'trusting__noteuser__user', 'trusted', 'trusted__noteuser__user']
 | 
			
		||||
    ordering_fields = ['trusting', 'trusted', ]
 | 
			
		||||
 | 
			
		||||
    def get_serializer_class(self):
 | 
			
		||||
        serializer_class = self.serializer_class
 | 
			
		||||
        if self.request.method in ['PUT', 'PATCH']:
 | 
			
		||||
            # trust relationship can't change people involved
 | 
			
		||||
            serializer_class.Meta.read_only_fields = ('trusting', 'trusting',)
 | 
			
		||||
        return serializer_class
 | 
			
		||||
 | 
			
		||||
    def destroy(self, request, *args, **kwargs):
 | 
			
		||||
        instance = self.get_object()
 | 
			
		||||
        try:
 | 
			
		||||
            self.perform_destroy(instance)
 | 
			
		||||
        except ValidationError as e:
 | 
			
		||||
            return Response({e.code: str(e)}, status.HTTP_400_BAD_REQUEST)
 | 
			
		||||
        return Response(status=status.HTTP_204_NO_CONTENT)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AliasViewSet(ReadProtectedModelViewSet):
 | 
			
		||||
    """
 | 
			
		||||
    REST API View set.
 | 
			
		||||
    The djangorestframework plugin will get all `Alias` objects, serialize it to JSON with the given serializer,
 | 
			
		||||
    then render it on /api/aliases/
 | 
			
		||||
    then render it on /api/note/aliases/
 | 
			
		||||
    """
 | 
			
		||||
    queryset = Alias.objects
 | 
			
		||||
    serializer_class = AliasSerializer
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								apps/note/migrations/0006_trust.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								apps/note/migrations/0006_trust.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
# Generated by Django 2.2.24 on 2021-09-05 19:16
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
import django.db.models.deletion
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('note', '0005_auto_20210313_1235'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.CreateModel(
 | 
			
		||||
            name='Trust',
 | 
			
		||||
            fields=[
 | 
			
		||||
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
 | 
			
		||||
                ('trusted', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusted', to='note.Note', verbose_name='trusted')),
 | 
			
		||||
                ('trusting', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='trusting', to='note.Note', verbose_name='trusting')),
 | 
			
		||||
            ],
 | 
			
		||||
            options={
 | 
			
		||||
                'verbose_name': 'frienship',
 | 
			
		||||
                'verbose_name_plural': 'friendships',
 | 
			
		||||
                'unique_together': {('trusting', 'trusted')},
 | 
			
		||||
            },
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -1,13 +1,13 @@
 | 
			
		||||
# Copyright (C) 2018-2021 by BDE ENS Paris-Saclay
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
from .notes import Alias, Note, NoteClub, NoteSpecial, NoteUser
 | 
			
		||||
from .notes import Alias, Note, NoteClub, NoteSpecial, NoteUser, Trust
 | 
			
		||||
from .transactions import MembershipTransaction, Transaction, \
 | 
			
		||||
    TemplateCategory, TransactionTemplate, RecurrentTransaction, SpecialTransaction
 | 
			
		||||
 | 
			
		||||
__all__ = [
 | 
			
		||||
    # Notes
 | 
			
		||||
    'Alias', 'Note', 'NoteClub', 'NoteSpecial', 'NoteUser',
 | 
			
		||||
    'Alias', 'Trust', 'Note', 'NoteClub', 'NoteSpecial', 'NoteUser',
 | 
			
		||||
    # Transactions
 | 
			
		||||
    'MembershipTransaction', 'Transaction', 'TemplateCategory', 'TransactionTemplate',
 | 
			
		||||
    'RecurrentTransaction', 'SpecialTransaction',
 | 
			
		||||
 
 | 
			
		||||
@@ -217,6 +217,38 @@ class NoteSpecial(Note):
 | 
			
		||||
        return self.special_type
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Trust(models.Model):
 | 
			
		||||
    """
 | 
			
		||||
    A one-sided trust relationship bertween two users
 | 
			
		||||
 | 
			
		||||
    If another user considers you as your friend, you can transfer money from
 | 
			
		||||
    them
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    trusting = models.ForeignKey(
 | 
			
		||||
        Note,
 | 
			
		||||
        on_delete=models.CASCADE,
 | 
			
		||||
        related_name='trusting',
 | 
			
		||||
        verbose_name=_('trusting')
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    trusted = models.ForeignKey(
 | 
			
		||||
        Note,
 | 
			
		||||
        on_delete=models.CASCADE,
 | 
			
		||||
        related_name='trusted',
 | 
			
		||||
        verbose_name=_('trusted')
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name = _("frienship")
 | 
			
		||||
        verbose_name_plural = _("friendships")
 | 
			
		||||
        unique_together = ("trusting", "trusted")
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return _("Friendship between {trusting} and {trusted}").format(
 | 
			
		||||
            trusting=str(self.trusting), trusted=str(self.trusted))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Alias(models.Model):
 | 
			
		||||
    """
 | 
			
		||||
    points toward  a :model:`note.NoteUser` or :model;`note.NoteClub` instance.
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from note_kfet.middlewares import get_current_request
 | 
			
		||||
from permission.backends import PermissionBackend
 | 
			
		||||
 | 
			
		||||
from .models.notes import Alias
 | 
			
		||||
from .models.notes import Alias, Trust
 | 
			
		||||
from .models.transactions import Transaction, TransactionTemplate
 | 
			
		||||
from .templatetags.pretty_money import pretty_money
 | 
			
		||||
 | 
			
		||||
@@ -148,6 +148,31 @@ DELETE_TEMPLATE = """
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TrustTable(tables.Table):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        attrs = {
 | 
			
		||||
            'class': 'table table condensed table-striped',
 | 
			
		||||
            'id': "trust_table"
 | 
			
		||||
        }
 | 
			
		||||
        model = Trust
 | 
			
		||||
        fields = ("trusted",)
 | 
			
		||||
        template_name = 'django_tables2/bootstrap4.html'
 | 
			
		||||
 | 
			
		||||
    show_header = False
 | 
			
		||||
    trusted = tables.Column(attrs={'td': {'class': 'text_center'}})
 | 
			
		||||
 | 
			
		||||
    delete_col = tables.TemplateColumn(
 | 
			
		||||
        template_code=DELETE_TEMPLATE,
 | 
			
		||||
        extra_context={"delete_trans": _('delete')},
 | 
			
		||||
        attrs={
 | 
			
		||||
            'td': {
 | 
			
		||||
                'class': lambda record: 'col-sm-1'
 | 
			
		||||
                + (' d-none' if not PermissionBackend.check_perm(
 | 
			
		||||
                    get_current_request(), "note.delete_trust", record)
 | 
			
		||||
                   else '')}},
 | 
			
		||||
        verbose_name=_("Delete"),)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AliasTable(tables.Table):
 | 
			
		||||
    class Meta:
 | 
			
		||||
        attrs = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1967,7 +1967,7 @@
 | 
			
		||||
				"note",
 | 
			
		||||
				"transaction"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "[\"AND\", [\"OR\", {\"source\": [\"club\", \"note\"]}, {\"destination\": [\"club\", \"note\"]}], [\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": true}, {\"destination__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": false}]]",
 | 
			
		||||
			"query": "[\"AND\", [\"OR\", {\"source\": [\"club\", \"note\"]}, {\"destination\": [\"club\", \"note\"]}], [\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": false}, {\"destination__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": true}]]",
 | 
			
		||||
			"type": "change",
 | 
			
		||||
			"mask": 2,
 | 
			
		||||
			"field": "valid",
 | 
			
		||||
@@ -2607,7 +2607,7 @@
 | 
			
		||||
				"note",
 | 
			
		||||
				"transaction"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "[\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": true}, {\"destination__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": false}]",
 | 
			
		||||
			"query": "[\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": false}, {\"destination__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": true}]",
 | 
			
		||||
			"type": "change",
 | 
			
		||||
			"mask": 2,
 | 
			
		||||
			"field": "valid",
 | 
			
		||||
@@ -2623,7 +2623,7 @@
 | 
			
		||||
				"note",
 | 
			
		||||
				"transaction"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "[\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": true}, {\"destination__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": false}]",
 | 
			
		||||
			"query": "[\"OR\", {\"source__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": false}, {\"destination__balance__gte\": {\"F\": [\"SUB\", [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]], 5000]}, \"valid\": true}]",
 | 
			
		||||
			"type": "change",
 | 
			
		||||
			"mask": 2,
 | 
			
		||||
			"field": "invalidity_reason",
 | 
			
		||||
@@ -2967,6 +2967,118 @@
 | 
			
		||||
			"description": "Supprimer une application OAuth2"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 190,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"trust"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "{\"trusting\": [\"user\", \"note\"]}",
 | 
			
		||||
			"type": "delete",
 | 
			
		||||
			"mask": 1,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": false,
 | 
			
		||||
			"description": "Supprimer une amitié à sa note"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 191,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"trust"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "{\"trusting\": [\"user\", \"note\"]}",
 | 
			
		||||
			"type": "add",
 | 
			
		||||
			"mask": 1,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": false,
 | 
			
		||||
			"description": "Ajouter une amitié à sa note"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 192,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"trust"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "{\"trusting__is_active\": true}",
 | 
			
		||||
			"type": "add",
 | 
			
		||||
			"mask": 1,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": false,
 | 
			
		||||
			"description": "Ajouter une amitié à une note non bloquée"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 193,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"trust"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "{\"trusting__is_active\": true}",
 | 
			
		||||
			"type": "delete",
 | 
			
		||||
			"mask": 3,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": false,
 | 
			
		||||
			"description": "Supprimer une amitié à une note non bloquée"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 194,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"trust"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "{}",
 | 
			
		||||
			"type": "view",
 | 
			
		||||
			"mask": 3,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": false,
 | 
			
		||||
			"description": "Voir toutes les amitiés, y compris celles des non adhérents"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 195,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"trust"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "{\"trusting__noteuser__user\": [\"user\"]}",
 | 
			
		||||
			"type": "view",
 | 
			
		||||
			"mask": 1,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": true,
 | 
			
		||||
			"description": "Voir ses propres amitiés, pour toujours"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.permission",
 | 
			
		||||
		"pk": 196,
 | 
			
		||||
		"fields": {
 | 
			
		||||
			"model": [
 | 
			
		||||
				"note",
 | 
			
		||||
				"transaction"
 | 
			
		||||
			],
 | 
			
		||||
			"query": "[\"AND\", {\"source__trusting__trusted\": [\"user\", \"note\"]}, [\"OR\", {\"source__balance__gte\": {\"F\": [\"MUL\", [\"F\", \"amount\"], [\"F\", \"quantity\"]]}}, {\"valid\": false}]]",
 | 
			
		||||
			"type": "add",
 | 
			
		||||
			"mask": 1,
 | 
			
		||||
			"field": "",
 | 
			
		||||
			"permanent": false,
 | 
			
		||||
			"description": "Transférer de l'argent depuis une note amie en restant positif"
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		"model": "permission.role",
 | 
			
		||||
		"pk": 1,
 | 
			
		||||
@@ -3001,7 +3113,11 @@
 | 
			
		||||
				186,
 | 
			
		||||
				187,
 | 
			
		||||
				188,
 | 
			
		||||
				189
 | 
			
		||||
				189,
 | 
			
		||||
                190,
 | 
			
		||||
                191,
 | 
			
		||||
                195,
 | 
			
		||||
                196
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
@@ -3042,7 +3158,9 @@
 | 
			
		||||
				158,
 | 
			
		||||
				159,
 | 
			
		||||
				160,
 | 
			
		||||
				179
 | 
			
		||||
				179,
 | 
			
		||||
                189,
 | 
			
		||||
                190
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
@@ -3192,7 +3310,10 @@
 | 
			
		||||
				176,
 | 
			
		||||
				177,
 | 
			
		||||
				178,
 | 
			
		||||
				183
 | 
			
		||||
                188,
 | 
			
		||||
				183,
 | 
			
		||||
                186,
 | 
			
		||||
                187
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
@@ -3386,7 +3507,14 @@
 | 
			
		||||
				186,
 | 
			
		||||
				187,
 | 
			
		||||
				188,
 | 
			
		||||
				189
 | 
			
		||||
				189,
 | 
			
		||||
                190,
 | 
			
		||||
                191,
 | 
			
		||||
                192,
 | 
			
		||||
                193,
 | 
			
		||||
                194,
 | 
			
		||||
                195,
 | 
			
		||||
                196
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								apps/treasury/migrations/0005_auto_20230129_2348.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								apps/treasury/migrations/0005_auto_20230129_2348.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2.28 on 2023-01-29 22:48
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('treasury', '0004_auto_20211005_1544'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='invoice',
 | 
			
		||||
            name='bde',
 | 
			
		||||
            field=models.CharField(choices=[('TotalistSpies', 'Tota[list]Spies'), ('Saperlistpopette', 'Saper[list]popette'), ('Finalist', 'Fina[list]'), ('Listorique', '[List]orique'), ('Satellist', 'Satel[list]'), ('Monopolist', 'Monopo[list]'), ('Kataclist', 'Katac[list]')], default='TotalistSpies', max_length=32, verbose_name='BDE'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
@@ -28,8 +28,9 @@ class Invoice(models.Model):
 | 
			
		||||
 | 
			
		||||
    bde = models.CharField(
 | 
			
		||||
        max_length=32,
 | 
			
		||||
        default='Saperlistpopette',
 | 
			
		||||
        default='TotalistSpies',
 | 
			
		||||
        choices=(
 | 
			
		||||
	    ('TotalistSpies', 'Tota[list]Spies'),
 | 
			
		||||
            ('Saperlistpopette', 'Saper[list]popette'),
 | 
			
		||||
            ('Finalist', 'Fina[list]'),
 | 
			
		||||
            ('Listorique', '[List]orique'),
 | 
			
		||||
@@ -95,7 +96,7 @@ class Invoice(models.Model):
 | 
			
		||||
        products = self.products.all()
 | 
			
		||||
 | 
			
		||||
        self.place = "Gif-sur-Yvette"
 | 
			
		||||
        self.my_name = "BDE ENS Cachan"
 | 
			
		||||
        self.my_name = "BDE ENS Paris Saclay"
 | 
			
		||||
        self.my_address_street = "4 avenue des Sciences"
 | 
			
		||||
        self.my_city = "91190 Gif-sur-Yvette"
 | 
			
		||||
        self.bank_code = 30003
 | 
			
		||||
@@ -310,8 +311,8 @@ class SogeCredit(models.Model):
 | 
			
		||||
        amount = sum(transaction.total for transaction in self.transactions.all())
 | 
			
		||||
        if 'wei' in settings.INSTALLED_APPS:
 | 
			
		||||
            from wei.models import WEIMembership
 | 
			
		||||
            if not WEIMembership.objects.filter(club__weiclub__year=datetime.date.today().year, user=self.user)\
 | 
			
		||||
                    .exists():
 | 
			
		||||
            if not WEIMembership.objects\
 | 
			
		||||
                    .filter(club__weiclub__year=self.credit_transaction.created_at.year, user=self.user).exists():
 | 
			
		||||
                # 80 € for people that don't go to WEI
 | 
			
		||||
                amount += 8000
 | 
			
		||||
        return amount
 | 
			
		||||
@@ -329,17 +330,18 @@ class SogeCredit(models.Model):
 | 
			
		||||
        bde_qs = Membership.objects.filter(user=self.user, club=bde, date_start__gte=bde.membership_start)
 | 
			
		||||
        kfet_qs = Membership.objects.filter(user=self.user, club=kfet, date_start__gte=kfet.membership_start)
 | 
			
		||||
 | 
			
		||||
        if bde_qs.exists():
 | 
			
		||||
            m = bde_qs.get()
 | 
			
		||||
            if MembershipTransaction.objects.filter(membership=m).exists():  # non-free membership
 | 
			
		||||
                if m.transaction not in self.transactions.all():
 | 
			
		||||
                    self.transactions.add(m.transaction)
 | 
			
		||||
 | 
			
		||||
        if kfet_qs.exists():
 | 
			
		||||
            m = kfet_qs.get()
 | 
			
		||||
            if MembershipTransaction.objects.filter(membership=m).exists():  # non-free membership
 | 
			
		||||
                if m.transaction not in self.transactions.all():
 | 
			
		||||
                    self.transactions.add(m.transaction)
 | 
			
		||||
## Soge do not pay BDE and kfet memberships this year (2022-2023)
 | 
			
		||||
#        if bde_qs.exists():
 | 
			
		||||
#            m = bde_qs.get()
 | 
			
		||||
#            if MembershipTransaction.objects.filter(membership=m).exists():  # non-free membership
 | 
			
		||||
#                if m.transaction not in self.transactions.all():
 | 
			
		||||
#                    self.transactions.add(m.transaction)
 | 
			
		||||
#
 | 
			
		||||
#        if kfet_qs.exists():
 | 
			
		||||
#            m = kfet_qs.get()
 | 
			
		||||
#            if MembershipTransaction.objects.filter(membership=m).exists():  # non-free membership
 | 
			
		||||
#                if m.transaction not in self.transactions.all():
 | 
			
		||||
#                    self.transactions.add(m.transaction)
 | 
			
		||||
 | 
			
		||||
        if 'wei' in settings.INSTALLED_APPS:
 | 
			
		||||
            from wei.models import WEIClub
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								apps/treasury/static/img/TotalistSpies.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								apps/treasury/static/img/TotalistSpies.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.0 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								apps/treasury/static/img/TotalistSpies_bg.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								apps/treasury/static/img/TotalistSpies_bg.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 35 KiB  | 
@@ -14,14 +14,17 @@ from .base import WEISurvey, WEISurveyInformation, WEISurveyAlgorithm, WEIBusInf
 | 
			
		||||
from ...models import WEIMembership
 | 
			
		||||
 | 
			
		||||
WORDS = [
 | 
			
		||||
    '13 organisé', '3ième mi temps', 'Années 2000', 'Apéro', 'BBQ', 'BP', 'Beauf', 'Binge drinking', 'Bon enfant',
 | 
			
		||||
    'Cartouche', 'Catacombes', 'Chansons paillardes', 'Chansons populaires', 'Chanteur', 'Chartreuse', 'Chill',
 | 
			
		||||
    'Core', 'DJ', 'Dancefloor', 'Danse', 'David Guetta', 'Disco', 'Eau de vie', 'Électro', 'Escalade', 'Familial',
 | 
			
		||||
    'Fanfare', 'Fracassage', 'Féria', 'Hard rock', 'Hoeggarden', 'House', 'Huit-six', 'IPA', 'Inclusif', 'Inferno',
 | 
			
		||||
    'Introverti', 'Jager bomb', 'Jazz', 'Jeux d\'alcool', 'Jeux de rôles', 'Jeux vidéo', 'Jul', 'Jus de fruit',
 | 
			
		||||
    'Karaoké', 'LGBTQI+', 'Lady Gaga', 'Loup garou', 'Morning beer', 'Métal', 'Nuit blanche', 'Ovalie', 'Psychedelic',
 | 
			
		||||
    'Pétanque', 'Rave', 'Reggae', 'Rhum', 'Ricard', 'Rock', 'Rosé', 'Rétro', 'Séducteur', 'Techno', 'Thérapie taxi',
 | 
			
		||||
    'Théâtre', 'Trap', 'Turn up', 'Underground', 'Volley', 'Wati B', 'Zinédine Zidane',
 | 
			
		||||
	'ABBA', 'After', 'Alcoolique anonyme', 'Ambiance festive', 'Années 2000', 'Apéro', 'Art',
 | 
			
		||||
	'Baby foot billard biere pong', 'BBQ', 'Before', 'Bière pong', 'Bon enfant', 'Calme', 'Canapé',
 | 
			
		||||
	'Chanson paillarde', 'Chanson populaire', 'Chartreuse', 'Cheerleader', 'Chill', 'Choré',
 | 
			
		||||
	'Cinéma', 'Cocktail', 'Comédie musicle', 'Commercial', 'Copaing', 'Danse', 'Dancefloor',
 | 
			
		||||
	'Electro', 'Fanfare', 'Gin tonic', 'Inclusif', 'Jazz', "Jeux d'alcool", 'Jeux de carte',
 | 
			
		||||
	'Jeux de rôle', 'Jeux de société', 'JUL', 'Jus de fruit', 'Kfet', 'Kleptomanie assurée',
 | 
			
		||||
	'LGBTQ+', 'Livre', 'Morning beer', 'Musique', 'NAPS', 'Paillettes', 'Pastis', 'Paté Hénaff',
 | 
			
		||||
	'Peluche', 'Pena baiona', "Peu d'alcool", 'Pilier de bar', 'PMU', 'Poulpe', 'Punch', 'Rap',
 | 
			
		||||
	'Réveil', 'Rock', 'Rugby', 'Sandwich', 'Serge', 'Shot', 'Sociable', 'Spectacle', 'Techno',
 | 
			
		||||
	'Techno house', 'Thérapie Taxi', 'Tradition kchanaises', 'Troisième mi-temps', 'Turn up',
 | 
			
		||||
	'Vodka', 'Vodka pomme', 'Volley', 'Vomi stratégique'
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								apps/wei/migrations/0004_auto_20220904_2325.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								apps/wei/migrations/0004_auto_20220904_2325.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2.26 on 2022-09-04 21:25
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('wei', '0003_bus_size'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='weiclub',
 | 
			
		||||
            name='year',
 | 
			
		||||
            field=models.PositiveIntegerField(default=2022, unique=True, verbose_name='year'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
							
								
								
									
										18
									
								
								apps/wei/migrations/0005_auto_20230128_1850.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								apps/wei/migrations/0005_auto_20230128_1850.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
# Generated by Django 2.2.28 on 2023-01-28 17:50
 | 
			
		||||
 | 
			
		||||
from django.db import migrations, models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Migration(migrations.Migration):
 | 
			
		||||
 | 
			
		||||
    dependencies = [
 | 
			
		||||
        ('wei', '0004_auto_20220904_2325'),
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    operations = [
 | 
			
		||||
        migrations.AlterField(
 | 
			
		||||
            model_name='weiclub',
 | 
			
		||||
            name='year',
 | 
			
		||||
            field=models.PositiveIntegerField(default=2023, unique=True, verbose_name='year'),
 | 
			
		||||
        ),
 | 
			
		||||
    ]
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -7,16 +7,16 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: \n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2021-10-07 22:55+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2020-11-16 20:02+0000\n"
 | 
			
		||||
"Last-Translator: Yohann D'ANELLO <ynerant@crans.org>\n"
 | 
			
		||||
"POT-Creation-Date: 2022-04-10 22:34+0200\n"
 | 
			
		||||
"PO-Revision-Date: 2022-04-11 22:05+0200\n"
 | 
			
		||||
"Last-Translator: elkmaennchen <elkmaennchen@crans.org>\n"
 | 
			
		||||
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
 | 
			
		||||
"Language: fr\n"
 | 
			
		||||
"MIME-Version: 1.0\n"
 | 
			
		||||
"Content-Type: text/plain; charset=UTF-8\n"
 | 
			
		||||
"Content-Transfer-Encoding: 8bit\n"
 | 
			
		||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
 | 
			
		||||
"X-Generator: Weblate 4.3.2\n"
 | 
			
		||||
"X-Generator: Poedit 3.0\n"
 | 
			
		||||
 | 
			
		||||
#: apps/activity/apps.py:10 apps/activity/models.py:151
 | 
			
		||||
#: apps/activity/models.py:167
 | 
			
		||||
@@ -56,7 +56,7 @@ msgstr "Vous ne pouvez pas inviter plus de 3 personnes à cette activité."
 | 
			
		||||
#: apps/member/models.py:199
 | 
			
		||||
#: apps/member/templates/member/includes/club_info.html:4
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:4
 | 
			
		||||
#: apps/note/models/notes.py:231 apps/note/models/transactions.py:26
 | 
			
		||||
#: apps/note/models/notes.py:263 apps/note/models/transactions.py:26
 | 
			
		||||
#: apps/note/models/transactions.py:46 apps/note/models/transactions.py:301
 | 
			
		||||
#: apps/permission/models.py:330
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:16
 | 
			
		||||
@@ -114,7 +114,7 @@ msgstr "Lieu où l'activité est organisée, par exemple la Kfet."
 | 
			
		||||
msgid "type"
 | 
			
		||||
msgstr "type"
 | 
			
		||||
 | 
			
		||||
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:305
 | 
			
		||||
#: apps/activity/models.py:89 apps/logs/models.py:22 apps/member/models.py:307
 | 
			
		||||
#: apps/note/models/notes.py:148 apps/treasury/models.py:285
 | 
			
		||||
#: apps/wei/models.py:173 apps/wei/templates/wei/attribute_bus_1A.html:13
 | 
			
		||||
#: apps/wei/templates/wei/survey.html:15
 | 
			
		||||
@@ -295,7 +295,7 @@ msgstr "Invité supprimé"
 | 
			
		||||
#: apps/note/models/transactions.py:257
 | 
			
		||||
#: apps/note/templates/note/transaction_form.html:17
 | 
			
		||||
#: apps/note/templates/note/transaction_form.html:152
 | 
			
		||||
#: note_kfet/templates/base.html:73
 | 
			
		||||
#: note_kfet/templates/base.html:72
 | 
			
		||||
msgid "Transfer"
 | 
			
		||||
msgstr "Virement"
 | 
			
		||||
 | 
			
		||||
@@ -388,7 +388,7 @@ msgid "validate"
 | 
			
		||||
msgstr "valider"
 | 
			
		||||
 | 
			
		||||
#: apps/activity/templates/activity/includes/activity_info.html:71
 | 
			
		||||
#: apps/logs/models.py:64 apps/note/tables.py:195
 | 
			
		||||
#: apps/logs/models.py:64 apps/note/tables.py:220
 | 
			
		||||
msgid "edit"
 | 
			
		||||
msgstr "modifier"
 | 
			
		||||
 | 
			
		||||
@@ -400,7 +400,7 @@ msgstr "Inviter"
 | 
			
		||||
msgid "Create new activity"
 | 
			
		||||
msgstr "Créer une nouvelle activité"
 | 
			
		||||
 | 
			
		||||
#: apps/activity/views.py:67 note_kfet/templates/base.html:91
 | 
			
		||||
#: apps/activity/views.py:67 note_kfet/templates/base.html:90
 | 
			
		||||
msgid "Activities"
 | 
			
		||||
msgstr "Activités"
 | 
			
		||||
 | 
			
		||||
@@ -466,9 +466,9 @@ msgstr "nouvelles données"
 | 
			
		||||
msgid "create"
 | 
			
		||||
msgstr "créer"
 | 
			
		||||
 | 
			
		||||
#: apps/logs/models.py:65 apps/note/tables.py:165 apps/note/tables.py:211
 | 
			
		||||
#: apps/permission/models.py:127 apps/treasury/tables.py:38
 | 
			
		||||
#: apps/wei/tables.py:74
 | 
			
		||||
#: apps/logs/models.py:65 apps/note/tables.py:166 apps/note/tables.py:190
 | 
			
		||||
#: apps/note/tables.py:237 apps/permission/models.py:127
 | 
			
		||||
#: apps/treasury/tables.py:38 apps/wei/tables.py:74
 | 
			
		||||
msgid "delete"
 | 
			
		||||
msgstr "supprimer"
 | 
			
		||||
 | 
			
		||||
@@ -507,11 +507,11 @@ msgstr "cotisation pour adhérer (normalien élève)"
 | 
			
		||||
msgid "membership fee (unpaid students)"
 | 
			
		||||
msgstr "cotisation pour adhérer (normalien étudiant)"
 | 
			
		||||
 | 
			
		||||
#: apps/member/admin.py:65 apps/member/models.py:317
 | 
			
		||||
#: apps/member/admin.py:65 apps/member/models.py:319
 | 
			
		||||
msgid "roles"
 | 
			
		||||
msgstr "rôles"
 | 
			
		||||
 | 
			
		||||
#: apps/member/admin.py:66 apps/member/models.py:331
 | 
			
		||||
#: apps/member/admin.py:66 apps/member/models.py:333
 | 
			
		||||
msgid "fee"
 | 
			
		||||
msgstr "cotisation"
 | 
			
		||||
 | 
			
		||||
@@ -547,7 +547,7 @@ msgstr "Taille maximale : 2 Mo"
 | 
			
		||||
msgid "This image cannot be loaded."
 | 
			
		||||
msgstr "Cette image ne peut pas être chargée."
 | 
			
		||||
 | 
			
		||||
#: apps/member/forms.py:141 apps/member/views.py:102
 | 
			
		||||
#: apps/member/forms.py:141 apps/member/views.py:103
 | 
			
		||||
#: apps/registration/forms.py:33 apps/registration/views.py:262
 | 
			
		||||
msgid "An alias with a similar name already exists."
 | 
			
		||||
msgstr "Un alias avec un nom similaire existe déjà."
 | 
			
		||||
@@ -610,14 +610,14 @@ msgid "hash"
 | 
			
		||||
msgstr "haché"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:38
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:35
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:43
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:40
 | 
			
		||||
#: apps/wei/templates/wei/weimembership_form.html:44
 | 
			
		||||
msgid "phone number"
 | 
			
		||||
msgstr "numéro de téléphone"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:45
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:29
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:37
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:34
 | 
			
		||||
#: apps/wei/templates/wei/weimembership_form.html:38
 | 
			
		||||
msgid "section"
 | 
			
		||||
@@ -705,14 +705,14 @@ msgid "Year of entry to the school (None if not ENS student)"
 | 
			
		||||
msgstr "Année d'entrée dans l'école (None si non-étudiant·e de l'ENS)"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:83
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:39
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:47
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:37
 | 
			
		||||
#: apps/wei/templates/wei/weimembership_form.html:41
 | 
			
		||||
msgid "address"
 | 
			
		||||
msgstr "adresse"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:90
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:42
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:50
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:43
 | 
			
		||||
#: apps/wei/templates/wei/weimembership_form.html:47
 | 
			
		||||
msgid "paid"
 | 
			
		||||
@@ -784,7 +784,7 @@ msgstr "Activez votre compte Note Kfet"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:204
 | 
			
		||||
#: apps/member/templates/member/includes/club_info.html:55
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:32
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:40
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:22
 | 
			
		||||
#: apps/wei/templates/wei/base.html:70
 | 
			
		||||
#: apps/wei/templates/wei/weimembership_form.html:20
 | 
			
		||||
@@ -833,46 +833,46 @@ msgstr ""
 | 
			
		||||
"Date maximale d'une fin d'adhésion, après laquelle les adhérents doivent la "
 | 
			
		||||
"renouveler."
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:286 apps/member/models.py:311
 | 
			
		||||
#: apps/member/models.py:288 apps/member/models.py:313
 | 
			
		||||
#: apps/note/models/notes.py:176
 | 
			
		||||
msgid "club"
 | 
			
		||||
msgstr "club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:287
 | 
			
		||||
#: apps/member/models.py:289
 | 
			
		||||
msgid "clubs"
 | 
			
		||||
msgstr "clubs"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:322
 | 
			
		||||
#: apps/member/models.py:324
 | 
			
		||||
msgid "membership starts on"
 | 
			
		||||
msgstr "l'adhésion commence le"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:326
 | 
			
		||||
#: apps/member/models.py:328
 | 
			
		||||
msgid "membership ends on"
 | 
			
		||||
msgstr "l'adhésion finit le"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:428
 | 
			
		||||
#: apps/member/models.py:430
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "The role {role} does not apply to the club {club}."
 | 
			
		||||
msgstr "Le rôle {role} ne s'applique pas au club {club}."
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:437 apps/member/views.py:651
 | 
			
		||||
#: apps/member/models.py:439 apps/member/views.py:712
 | 
			
		||||
msgid "User is already a member of the club"
 | 
			
		||||
msgstr "L'utilisateur est déjà membre du club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:449 apps/member/views.py:660
 | 
			
		||||
#: apps/member/models.py:451 apps/member/views.py:721
 | 
			
		||||
msgid "User is not a member of the parent club"
 | 
			
		||||
msgstr "L'utilisateur n'est pas membre du club parent"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:502
 | 
			
		||||
#: apps/member/models.py:504
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "Membership of {user} for the club {club}"
 | 
			
		||||
msgstr "Adhésion de {user} pour le club {club}"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:505 apps/note/models/transactions.py:389
 | 
			
		||||
#: apps/member/models.py:507 apps/note/models/transactions.py:389
 | 
			
		||||
msgid "membership"
 | 
			
		||||
msgstr "adhésion"
 | 
			
		||||
 | 
			
		||||
#: apps/member/models.py:506
 | 
			
		||||
#: apps/member/models.py:508
 | 
			
		||||
msgid "memberships"
 | 
			
		||||
msgstr "adhésions"
 | 
			
		||||
 | 
			
		||||
@@ -924,7 +924,7 @@ msgid "Account #"
 | 
			
		||||
msgstr "Compte n°"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/base.html:48
 | 
			
		||||
#: apps/member/templates/member/base.html:62 apps/member/views.py:59
 | 
			
		||||
#: apps/member/templates/member/base.html:62 apps/member/views.py:60
 | 
			
		||||
#: apps/registration/templates/registration/future_profile_detail.html:48
 | 
			
		||||
#: apps/wei/templates/wei/weimembership_form.html:117
 | 
			
		||||
msgid "Update Profile"
 | 
			
		||||
@@ -985,13 +985,14 @@ msgstr ""
 | 
			
		||||
"seront à nouveau possible."
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/club_alias.html:10
 | 
			
		||||
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:253
 | 
			
		||||
#: apps/member/views.py:456
 | 
			
		||||
#: apps/member/templates/member/profile_alias.html:10 apps/member/views.py:287
 | 
			
		||||
#: apps/member/views.py:517
 | 
			
		||||
msgid "Note aliases"
 | 
			
		||||
msgstr "Alias de la note"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/club_alias.html:20
 | 
			
		||||
#: apps/member/templates/member/profile_alias.html:19
 | 
			
		||||
#: apps/member/templates/member/profile_trust.html:19
 | 
			
		||||
#: apps/treasury/tables.py:99
 | 
			
		||||
#: apps/treasury/templates/treasury/sogecredit_list.html:34
 | 
			
		||||
#: apps/treasury/templates/treasury/sogecredit_list.html:73
 | 
			
		||||
@@ -1044,7 +1045,7 @@ msgid "membership fee"
 | 
			
		||||
msgstr "cotisation pour adhérer"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/includes/club_info.html:43
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:47
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:55
 | 
			
		||||
#: apps/treasury/templates/treasury/sogecredit_detail.html:24
 | 
			
		||||
#: apps/wei/templates/wei/base.html:60
 | 
			
		||||
msgid "balance"
 | 
			
		||||
@@ -1052,7 +1053,7 @@ msgstr "solde du compte"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/includes/club_info.html:47
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:20
 | 
			
		||||
#: apps/note/models/notes.py:255 apps/wei/templates/wei/base.html:66
 | 
			
		||||
#: apps/note/models/notes.py:287 apps/wei/templates/wei/base.html:66
 | 
			
		||||
msgid "aliases"
 | 
			
		||||
msgstr "alias"
 | 
			
		||||
 | 
			
		||||
@@ -1076,7 +1077,16 @@ msgstr "mot de passe"
 | 
			
		||||
msgid "Change password"
 | 
			
		||||
msgstr "Changer le mot de passe"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:55
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:28
 | 
			
		||||
#: apps/note/models/notes.py:244
 | 
			
		||||
msgid "friendships"
 | 
			
		||||
msgstr "amitiés"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:32
 | 
			
		||||
msgid "Manage friendships"
 | 
			
		||||
msgstr "Gérer les amitiés"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/includes/profile_info.html:63
 | 
			
		||||
msgid "API token"
 | 
			
		||||
msgstr "Accès API"
 | 
			
		||||
 | 
			
		||||
@@ -1148,6 +1158,23 @@ msgstr "Cliquez ici pour renvoyer un lien de validation."
 | 
			
		||||
msgid "View my memberships"
 | 
			
		||||
msgstr "Voir mes adhésions"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/profile_trust.html:10 apps/member/views.py:254
 | 
			
		||||
msgid "Note friendships"
 | 
			
		||||
msgstr "Amitiés note"
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/profile_trust.html:28
 | 
			
		||||
msgid ""
 | 
			
		||||
"Adding someone as a friend enables them to initiate transactions coming from "
 | 
			
		||||
"your account (while keeping your balance positive). This is designed to "
 | 
			
		||||
"simplify using note kfet transfers to transfer money between users. The "
 | 
			
		||||
"intent is that one person can make all transfers for a group of friends "
 | 
			
		||||
"without needing additional rights among them."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Ajouter quelqu'un⋅e en ami⋅e lui permet de me prélever de l'argent (tant que "
 | 
			
		||||
"ma note reste positive). Ceci sert à simplifier les remboursements entre "
 | 
			
		||||
"ami⋅es via note. En effet, une personne peut effectuer tous les transferts "
 | 
			
		||||
"sans posséder de droits supplémentaires."
 | 
			
		||||
 | 
			
		||||
#: apps/member/templates/member/profile_update.html:18
 | 
			
		||||
msgid "Save Changes"
 | 
			
		||||
msgstr "Sauvegarder les changements"
 | 
			
		||||
@@ -1156,47 +1183,47 @@ msgstr "Sauvegarder les changements"
 | 
			
		||||
msgid "Registrations"
 | 
			
		||||
msgstr "Inscriptions"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:72 apps/registration/forms.py:23
 | 
			
		||||
#: apps/member/views.py:73 apps/registration/forms.py:23
 | 
			
		||||
msgid "This address must be valid."
 | 
			
		||||
msgstr "Cette adresse doit être valide."
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:139
 | 
			
		||||
#: apps/member/views.py:140
 | 
			
		||||
msgid "Profile detail"
 | 
			
		||||
msgstr "Détails de l'utilisateur"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:205
 | 
			
		||||
#: apps/member/views.py:206
 | 
			
		||||
msgid "Search user"
 | 
			
		||||
msgstr "Chercher un utilisateur"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:273
 | 
			
		||||
#: apps/member/views.py:308
 | 
			
		||||
msgid "Update note picture"
 | 
			
		||||
msgstr "Modifier la photo de la note"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:319
 | 
			
		||||
#: apps/member/views.py:354
 | 
			
		||||
msgid "Manage auth token"
 | 
			
		||||
msgstr "Gérer les jetons d'authentification"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:346
 | 
			
		||||
#: apps/member/views.py:381
 | 
			
		||||
msgid "Create new club"
 | 
			
		||||
msgstr "Créer un nouveau club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:365
 | 
			
		||||
#: apps/member/views.py:400
 | 
			
		||||
msgid "Search club"
 | 
			
		||||
msgstr "Chercher un club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:398
 | 
			
		||||
#: apps/member/views.py:433
 | 
			
		||||
msgid "Club detail"
 | 
			
		||||
msgstr "Détails du club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:479
 | 
			
		||||
#: apps/member/views.py:540
 | 
			
		||||
msgid "Update club"
 | 
			
		||||
msgstr "Modifier le club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:513
 | 
			
		||||
#: apps/member/views.py:574
 | 
			
		||||
msgid "Add new member to the club"
 | 
			
		||||
msgstr "Ajouter un nouveau membre au club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:642 apps/wei/views.py:973
 | 
			
		||||
#: apps/member/views.py:703 apps/wei/views.py:973
 | 
			
		||||
msgid ""
 | 
			
		||||
"This user don't have enough money to join this club, and can't have a "
 | 
			
		||||
"negative balance."
 | 
			
		||||
@@ -1204,19 +1231,19 @@ msgstr ""
 | 
			
		||||
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
 | 
			
		||||
"avoir un solde négatif."
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:664
 | 
			
		||||
#: apps/member/views.py:725
 | 
			
		||||
msgid "The membership must start after {:%m-%d-%Y}."
 | 
			
		||||
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:669
 | 
			
		||||
#: apps/member/views.py:730
 | 
			
		||||
msgid "The membership must begin before {:%m-%d-%Y}."
 | 
			
		||||
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:815
 | 
			
		||||
#: apps/member/views.py:876
 | 
			
		||||
msgid "Manage roles of an user in the club"
 | 
			
		||||
msgstr "Gérer les rôles d'un utilisateur dans le club"
 | 
			
		||||
 | 
			
		||||
#: apps/member/views.py:840
 | 
			
		||||
#: apps/member/views.py:901
 | 
			
		||||
msgid "Members of the club"
 | 
			
		||||
msgstr "Membres du club"
 | 
			
		||||
 | 
			
		||||
@@ -1234,7 +1261,7 @@ msgstr "destination"
 | 
			
		||||
msgid "amount"
 | 
			
		||||
msgstr "montant"
 | 
			
		||||
 | 
			
		||||
#: apps/note/api/serializers.py:183 apps/note/api/serializers.py:189
 | 
			
		||||
#: apps/note/api/serializers.py:199 apps/note/api/serializers.py:205
 | 
			
		||||
#: apps/note/models/transactions.py:228
 | 
			
		||||
msgid ""
 | 
			
		||||
"The transaction can't be saved since the source note or the destination note "
 | 
			
		||||
@@ -1366,30 +1393,47 @@ msgstr "note spéciale"
 | 
			
		||||
msgid "special notes"
 | 
			
		||||
msgstr "notes spéciales"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:237
 | 
			
		||||
#: apps/note/models/notes.py:232
 | 
			
		||||
msgid "trusting"
 | 
			
		||||
msgstr "note"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:239
 | 
			
		||||
msgid "trusted"
 | 
			
		||||
msgstr "ami"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:243
 | 
			
		||||
msgid "frienship"
 | 
			
		||||
msgstr "amitié"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:248
 | 
			
		||||
#, python-brace-format
 | 
			
		||||
msgid "Friendship between {trusting} and {trusted}"
 | 
			
		||||
msgstr "Amitié entre {trusting} et {trusted}"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:269
 | 
			
		||||
msgid "Invalid alias"
 | 
			
		||||
msgstr "Alias invalide"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:254
 | 
			
		||||
#: apps/note/models/notes.py:286
 | 
			
		||||
msgid "alias"
 | 
			
		||||
msgstr "alias"
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:278
 | 
			
		||||
#: apps/note/models/notes.py:310
 | 
			
		||||
msgid "Alias is too long."
 | 
			
		||||
msgstr "L'alias est trop long."
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:281
 | 
			
		||||
#: apps/note/models/notes.py:313
 | 
			
		||||
msgid ""
 | 
			
		||||
"This alias contains only complex character. Please use a more simple alias."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Cet alias ne contient que des caractères complexes. Merci d'utiliser un "
 | 
			
		||||
"alias plus simple."
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:285
 | 
			
		||||
#: apps/note/models/notes.py:317
 | 
			
		||||
msgid "An alias with a similar name already exists: {} "
 | 
			
		||||
msgstr "Un alias avec un nom similaire existe déjà : {} "
 | 
			
		||||
 | 
			
		||||
#: apps/note/models/notes.py:299
 | 
			
		||||
#: apps/note/models/notes.py:331
 | 
			
		||||
msgid "You can't delete your main alias."
 | 
			
		||||
msgstr "Vous ne pouvez pas supprimer votre alias principal."
 | 
			
		||||
 | 
			
		||||
@@ -1535,7 +1579,8 @@ msgstr "Cliquez pour valider"
 | 
			
		||||
msgid "No reason specified"
 | 
			
		||||
msgstr "Pas de motif spécifié"
 | 
			
		||||
 | 
			
		||||
#: apps/note/tables.py:169 apps/note/tables.py:213 apps/treasury/tables.py:39
 | 
			
		||||
#: apps/note/tables.py:173 apps/note/tables.py:194 apps/note/tables.py:239
 | 
			
		||||
#: apps/treasury/tables.py:39
 | 
			
		||||
#: apps/treasury/templates/treasury/invoice_confirm_delete.html:30
 | 
			
		||||
#: apps/treasury/templates/treasury/sogecredit_detail.html:65
 | 
			
		||||
#: apps/wei/tables.py:75 apps/wei/tables.py:118
 | 
			
		||||
@@ -1546,7 +1591,7 @@ msgstr "Pas de motif spécifié"
 | 
			
		||||
msgid "Delete"
 | 
			
		||||
msgstr "Supprimer"
 | 
			
		||||
 | 
			
		||||
#: apps/note/tables.py:197 apps/note/templates/note/conso_form.html:132
 | 
			
		||||
#: apps/note/tables.py:222 apps/note/templates/note/conso_form.html:132
 | 
			
		||||
#: apps/wei/tables.py:49 apps/wei/tables.py:50
 | 
			
		||||
#: apps/wei/templates/wei/base.html:89
 | 
			
		||||
#: apps/wei/templates/wei/bus_detail.html:20
 | 
			
		||||
@@ -1556,7 +1601,7 @@ msgstr "Supprimer"
 | 
			
		||||
msgid "Edit"
 | 
			
		||||
msgstr "Éditer"
 | 
			
		||||
 | 
			
		||||
#: apps/note/tables.py:201 apps/note/tables.py:224
 | 
			
		||||
#: apps/note/tables.py:226 apps/note/tables.py:253
 | 
			
		||||
msgid "Hide/Show"
 | 
			
		||||
msgstr "Afficher/Masquer"
 | 
			
		||||
 | 
			
		||||
@@ -1717,7 +1762,7 @@ msgstr "Chercher un bouton"
 | 
			
		||||
msgid "Update button"
 | 
			
		||||
msgstr "Modifier le bouton"
 | 
			
		||||
 | 
			
		||||
#: apps/note/views.py:151 note_kfet/templates/base.html:67
 | 
			
		||||
#: apps/note/views.py:151 note_kfet/templates/base.html:66
 | 
			
		||||
msgid "Consumptions"
 | 
			
		||||
msgstr "Consommations"
 | 
			
		||||
 | 
			
		||||
@@ -1915,7 +1960,7 @@ msgstr ""
 | 
			
		||||
"Vous n'avez pas la permission d'ajouter une instance du modèle « {model} » "
 | 
			
		||||
"avec ces paramètres. Merci de les corriger et de réessayer."
 | 
			
		||||
 | 
			
		||||
#: apps/permission/views.py:112 note_kfet/templates/base.html:109
 | 
			
		||||
#: apps/permission/views.py:112 note_kfet/templates/base.html:108
 | 
			
		||||
msgid "Rights"
 | 
			
		||||
msgstr "Droits"
 | 
			
		||||
 | 
			
		||||
@@ -2122,7 +2167,7 @@ msgstr ""
 | 
			
		||||
msgid "Invalidate pre-registration"
 | 
			
		||||
msgstr "Invalider l'inscription"
 | 
			
		||||
 | 
			
		||||
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:97
 | 
			
		||||
#: apps/treasury/apps.py:12 note_kfet/templates/base.html:96
 | 
			
		||||
msgid "Treasury"
 | 
			
		||||
msgstr "Trésorerie"
 | 
			
		||||
 | 
			
		||||
@@ -2530,7 +2575,7 @@ msgstr "Gérer les crédits de la Société générale"
 | 
			
		||||
 | 
			
		||||
#: apps/wei/apps.py:10 apps/wei/models.py:50 apps/wei/models.py:51
 | 
			
		||||
#: apps/wei/models.py:62 apps/wei/models.py:180
 | 
			
		||||
#: note_kfet/templates/base.html:103
 | 
			
		||||
#: note_kfet/templates/base.html:102
 | 
			
		||||
msgid "WEI"
 | 
			
		||||
msgstr "WEI"
 | 
			
		||||
 | 
			
		||||
@@ -2538,7 +2583,7 @@ msgstr "WEI"
 | 
			
		||||
msgid "The selected user is not validated. Please validate its account first"
 | 
			
		||||
msgstr ""
 | 
			
		||||
"L'utilisateur sélectionné n'est pas validé. Merci de d'abord valider son "
 | 
			
		||||
"compte."
 | 
			
		||||
"compte"
 | 
			
		||||
 | 
			
		||||
#: apps/wei/forms/registration.py:59 apps/wei/models.py:126
 | 
			
		||||
#: apps/wei/models.py:323
 | 
			
		||||
@@ -2579,7 +2624,7 @@ msgstr "Sélectionnez les rôles qui vous intéressent."
 | 
			
		||||
msgid "This team doesn't belong to the given bus."
 | 
			
		||||
msgstr "Cette équipe n'appartient pas à ce bus."
 | 
			
		||||
 | 
			
		||||
#: apps/wei/forms/surveys/wei2021.py:35
 | 
			
		||||
#: apps/wei/forms/surveys/wei2021.py:35 apps/wei/forms/surveys/wei2022.py:35
 | 
			
		||||
msgid "Choose a word:"
 | 
			
		||||
msgstr "Choisissez un mot :"
 | 
			
		||||
 | 
			
		||||
@@ -3140,19 +3185,19 @@ msgstr "Répartir les 1A dans les bus"
 | 
			
		||||
msgid "Attribute bus"
 | 
			
		||||
msgstr "Attribuer un bus"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/settings/base.py:161
 | 
			
		||||
#: note_kfet/settings/base.py:172
 | 
			
		||||
msgid "German"
 | 
			
		||||
msgstr "Allemand"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/settings/base.py:162
 | 
			
		||||
#: note_kfet/settings/base.py:173
 | 
			
		||||
msgid "English"
 | 
			
		||||
msgstr "Anglais"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/settings/base.py:163
 | 
			
		||||
#: note_kfet/settings/base.py:174
 | 
			
		||||
msgid "Spanish"
 | 
			
		||||
msgstr "Espagnol"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/settings/base.py:164
 | 
			
		||||
#: note_kfet/settings/base.py:175
 | 
			
		||||
msgid "French"
 | 
			
		||||
msgstr "Français"
 | 
			
		||||
 | 
			
		||||
@@ -3209,7 +3254,7 @@ msgstr ""
 | 
			
		||||
"erreur, qui sera corrigée rapidement. Vous pouvez désormais aller boire une "
 | 
			
		||||
"bière."
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/autocomplete_model.html:14
 | 
			
		||||
#: note_kfet/templates/autocomplete_model.html:15
 | 
			
		||||
msgid "Reset"
 | 
			
		||||
msgstr "Réinitialiser"
 | 
			
		||||
 | 
			
		||||
@@ -3217,34 +3262,34 @@ msgstr "Réinitialiser"
 | 
			
		||||
msgid "The ENS Paris-Saclay BDE note."
 | 
			
		||||
msgstr "La note du BDE de l'ENS Paris-Saclay."
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:79
 | 
			
		||||
#: note_kfet/templates/base.html:78
 | 
			
		||||
msgid "Users"
 | 
			
		||||
msgstr "Utilisateurs"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:85
 | 
			
		||||
#: note_kfet/templates/base.html:84
 | 
			
		||||
msgid "Clubs"
 | 
			
		||||
msgstr "Clubs"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:114
 | 
			
		||||
#: note_kfet/templates/base.html:113
 | 
			
		||||
msgid "Admin"
 | 
			
		||||
msgstr "Admin"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:128
 | 
			
		||||
#: note_kfet/templates/base.html:127
 | 
			
		||||
msgid "My account"
 | 
			
		||||
msgstr "Mon compte"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:131
 | 
			
		||||
#: note_kfet/templates/base.html:130
 | 
			
		||||
msgid "Log out"
 | 
			
		||||
msgstr "Se déconnecter"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:139
 | 
			
		||||
#: note_kfet/templates/base.html:138
 | 
			
		||||
#: note_kfet/templates/registration/signup.html:6
 | 
			
		||||
#: note_kfet/templates/registration/signup.html:11
 | 
			
		||||
#: note_kfet/templates/registration/signup.html:28
 | 
			
		||||
msgid "Sign up"
 | 
			
		||||
msgstr "Inscription"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:146
 | 
			
		||||
#: note_kfet/templates/base.html:145
 | 
			
		||||
#: note_kfet/templates/registration/login.html:6
 | 
			
		||||
#: note_kfet/templates/registration/login.html:15
 | 
			
		||||
#: note_kfet/templates/registration/login.html:38
 | 
			
		||||
@@ -3252,7 +3297,7 @@ msgstr "Inscription"
 | 
			
		||||
msgid "Log in"
 | 
			
		||||
msgstr "Se connecter"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:160
 | 
			
		||||
#: note_kfet/templates/base.html:159
 | 
			
		||||
msgid ""
 | 
			
		||||
"You are not a BDE member anymore. Please renew your membership if you want "
 | 
			
		||||
"to use the note."
 | 
			
		||||
@@ -3260,7 +3305,7 @@ msgstr ""
 | 
			
		||||
"Vous n'êtes plus adhérent BDE. Merci de réadhérer si vous voulez profiter de "
 | 
			
		||||
"la note."
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:166
 | 
			
		||||
#: note_kfet/templates/base.html:165
 | 
			
		||||
msgid ""
 | 
			
		||||
"Your e-mail address is not validated. Please check your mail inbox and click "
 | 
			
		||||
"on the validation link."
 | 
			
		||||
@@ -3268,7 +3313,7 @@ msgstr ""
 | 
			
		||||
"Votre adresse e-mail n'est pas validée. Merci de vérifier votre boîte mail "
 | 
			
		||||
"et de cliquer sur le lien de validation."
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:172
 | 
			
		||||
#: note_kfet/templates/base.html:171
 | 
			
		||||
msgid ""
 | 
			
		||||
"You declared that you opened a bank account in the Société générale. The "
 | 
			
		||||
"bank did not validate the creation of the account to the BDE, so the "
 | 
			
		||||
@@ -3282,11 +3327,11 @@ msgstr ""
 | 
			
		||||
"vérification peut durer quelques jours. Merci de vous assurer de bien aller "
 | 
			
		||||
"au bout de vos démarches."
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:195
 | 
			
		||||
#: note_kfet/templates/base.html:194
 | 
			
		||||
msgid "Contact us"
 | 
			
		||||
msgstr "Nous contacter"
 | 
			
		||||
 | 
			
		||||
#: note_kfet/templates/base.html:197
 | 
			
		||||
#: note_kfet/templates/base.html:196
 | 
			
		||||
msgid "Technical Support"
 | 
			
		||||
msgstr "Support technique"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -252,7 +252,7 @@ REST_FRAMEWORK = {
 | 
			
		||||
        'rest_framework.authentication.TokenAuthentication',
 | 
			
		||||
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
 | 
			
		||||
    ],
 | 
			
		||||
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
 | 
			
		||||
    'DEFAULT_PAGINATION_CLASS': 'apps.api.pagination.CustomPagination',
 | 
			
		||||
    'PAGE_SIZE': 20,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								note_kfet/static/css/custom.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										72
									
								
								note_kfet/static/css/custom.css
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -65,7 +65,10 @@ mark {
 | 
			
		||||
 | 
			
		||||
/* Last BDE colors */
 | 
			
		||||
.bg-primary {
 | 
			
		||||
    background-color: rgb(18, 67, 4) !important;
 | 
			
		||||
/*    background-color: rgb(18, 67, 4) !important; */
 | 
			
		||||
/* MODE VIEUXCON=ON */
 | 
			
		||||
/*    background-color: rgb(166, 0, 2) !important; */
 | 
			
		||||
    background-color: rgb(0, 0, 0) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
html {
 | 
			
		||||
@@ -80,15 +83,15 @@ body {
 | 
			
		||||
.btn-outline-primary:hover,
 | 
			
		||||
.btn-outline-primary:not(:disabled):not(.disabled).active,
 | 
			
		||||
.btn-outline-primary:not(:disabled):not(.disabled):active {
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    background-color: rgb(18, 67, 46);
 | 
			
		||||
    border-color: rgb(18, 67, 46);
 | 
			
		||||
   color:  rgb(241, 229, 52);
 | 
			
		||||
    background-color: rgb(228, 35, 132);
 | 
			
		||||
    border-color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-outline-primary {
 | 
			
		||||
    color: rgb(18, 67, 46);
 | 
			
		||||
    background-color: rgba(248, 249, 250, 0.9);
 | 
			
		||||
    border-color: rgb(18, 67, 46);
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    background-color: #000;
 | 
			
		||||
    border-color: #464647;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.turbolinks-progress-bar {
 | 
			
		||||
@@ -98,36 +101,63 @@ body {
 | 
			
		||||
.btn-primary:hover,
 | 
			
		||||
.btn-primary:not(:disabled):not(.disabled).active,
 | 
			
		||||
.btn-primary:not(:disabled):not(.disabled):active {
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    background-color: rgb(18, 67, 46);
 | 
			
		||||
    border-color: rgb(18, 67, 46);
 | 
			
		||||
    color:  rgb(241, 229, 52);
 | 
			
		||||
    background-color: rgb(228, 35, 132);
 | 
			
		||||
    border-color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-primary {
 | 
			
		||||
    color: rgba(248, 249, 250, 0.9); 
 | 
			
		||||
    background-color: rgb(28, 114, 10);
 | 
			
		||||
    border-color: rgb(18, 67, 46);
 | 
			
		||||
    color:  #fff; 
 | 
			
		||||
    background-color: #000;
 | 
			
		||||
    border-color: #adb5bd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.border-primary {
 | 
			
		||||
    border-color: rgb(28, 114, 10) !important; 
 | 
			
		||||
    border-color: rgb(228, 35, 132) !important; 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-secondary {
 | 
			
		||||
    color:  #fff;
 | 
			
		||||
    background-color: #000;
 | 
			
		||||
    border-color: #adb5bd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-secondary:hover,
 | 
			
		||||
.btn-secondary:not(:disabled):not(.disabled).active,
 | 
			
		||||
.btn-secondary:not(:disabled):not(.disabled):active {
 | 
			
		||||
    color:  rgb(241, 229, 52);
 | 
			
		||||
    background-color: rgb(228, 35, 132);
 | 
			
		||||
    border-color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.btn-outline-dark {
 | 
			
		||||
    color: #343a40;
 | 
			
		||||
    border-color: #343a40;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-outline-dark:hover,
 | 
			
		||||
.btn-outline-dark:not(:disabled):not(.disabled).active,
 | 
			
		||||
.btn-outline-dark:not(:disabled):not(.disabled):active {
 | 
			
		||||
    color:  rgb(241, 229, 52);
 | 
			
		||||
    background-color: rgb(228, 35, 132);
 | 
			
		||||
    border-color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
    color: rgb(28, 114, 10);
 | 
			
		||||
    color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:hover {
 | 
			
		||||
    color: rgb(122, 163, 75);
 | 
			
		||||
    color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-control:focus {
 | 
			
		||||
    box-shadow: 0 0 0 0.25rem rgba(122, 163, 75, 0.25);
 | 
			
		||||
    border-color: rgb(122, 163, 75);
 | 
			
		||||
    box-shadow: 0 0 0 0.25rem rgb(228 35 132 / 50%);
 | 
			
		||||
    border-color: rgb(228, 35, 132);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-outline-primary.focus {
 | 
			
		||||
  box-shadow: 0 0 0 0.25rem rgba(122, 163, 75, 0.5);
 | 
			
		||||
  box-shadow: 0 0 0 0.25rem rgb(228 35 132 / 10%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,21 +13,29 @@ $(document).ready(function () {
 | 
			
		||||
    $('#' + prefix + '_reset').removeClass('d-none')
 | 
			
		||||
 | 
			
		||||
    $.getJSON(api_url + (api_url.includes('?') ? '&' : '?') + 'format=json&search=^' + input + api_url_suffix, function (objects) {
 | 
			
		||||
      let html = ''
 | 
			
		||||
      let html = '<ul class="list-group list-group-flush" id="' + prefix + '_list">'
 | 
			
		||||
 | 
			
		||||
      objects.results.forEach(function (obj) {
 | 
			
		||||
        html += li(prefix + '_' + obj.id, obj[name_field])
 | 
			
		||||
      })
 | 
			
		||||
      html += '</ul>'
 | 
			
		||||
 | 
			
		||||
      const results_list = $('#' + prefix + '_list')
 | 
			
		||||
      results_list.html(html)
 | 
			
		||||
      target.tooltip({
 | 
			
		||||
        html: true,
 | 
			
		||||
        placement: 'bottom',
 | 
			
		||||
        trigger: 'manual',
 | 
			
		||||
        container: target.parent(),
 | 
			
		||||
        fallbackPlacement: 'clockwise'
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      target.attr("data-original-title", html).tooltip("show")
 | 
			
		||||
 | 
			
		||||
      objects.results.forEach(function (obj) {
 | 
			
		||||
        $('#' + prefix + '_' + obj.id).click(function () {
 | 
			
		||||
          target.val(obj[name_field])
 | 
			
		||||
          $('#' + prefix + '_pk').val(obj.id)
 | 
			
		||||
 | 
			
		||||
          results_list.html('')
 | 
			
		||||
          target.tooltip("hide")
 | 
			
		||||
          target.removeClass('is-invalid')
 | 
			
		||||
          target.addClass('is-valid')
 | 
			
		||||
 | 
			
		||||
@@ -37,8 +45,8 @@ $(document).ready(function () {
 | 
			
		||||
        if (input === obj[name_field]) { $('#' + prefix + '_pk').val(obj.id) }
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      if (results_list.children().length === 1 && e.originalEvent.keyCode >= 32) {
 | 
			
		||||
        results_list.children().first().trigger('click')
 | 
			
		||||
      if (objects.results.length === 1 && e.originalEvent.keyCode >= 32) {
 | 
			
		||||
        $('#' + prefix + '_' + objects.results[0].id).trigger('click')
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
 
 | 
			
		||||
@@ -9,9 +9,9 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
   name="{{ widget.name }}_name" autocomplete="off"
 | 
			
		||||
    {% for name, value in widget.attrs.items %}
 | 
			
		||||
        {% ifnotequal value False %}{{ name }}{% ifnotequal value True %}="{{ value|stringformat:'s' }}"{% endifnotequal %}{% endifnotequal %}
 | 
			
		||||
    {% endfor %}>
 | 
			
		||||
    {% endfor %}
 | 
			
		||||
    aria-describedby="{{widget.attrs.id}}_tooltip">
 | 
			
		||||
    {% if widget.resetable %}
 | 
			
		||||
        <a id="{{ widget.attrs.id }}_reset" class="btn btn-light autocomplete-reset{% if not widget.value %} d-none{% endif %}">{% trans "Reset" %}</a>
 | 
			
		||||
    {% endif %}
 | 
			
		||||
<ul class="list-group list-group-flush" id="{{ widget.attrs.id }}_list">
 | 
			
		||||
</ul>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,11 +23,11 @@ SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
            {% csrf_token %}
 | 
			
		||||
            {{ form|crispy }}
 | 
			
		||||
            {{ profile_form|crispy }}
 | 
			
		||||
            {{ soge_form|crispy }}
 | 
			
		||||
            {% comment "Soge not for membership (only WEI)" %} {{ soge_form|crispy }} {% endcomment %}
 | 
			
		||||
            <button class="btn btn-success" type="submit">
 | 
			
		||||
                {% trans "Sign up" %}
 | 
			
		||||
            </button>
 | 
			
		||||
        </form>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,3 +17,6 @@ django-tables2~=2.3.1
 | 
			
		||||
python-memcached~=1.59
 | 
			
		||||
phonenumbers~=8.9.10
 | 
			
		||||
Pillow>=5.4.1
 | 
			
		||||
oauthlib<3.2.1
 | 
			
		||||
lxml<4.9.2
 | 
			
		||||
zipp>=2.0.0,<2.0.1
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user