mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	List wei
This commit is contained in:
		| @@ -15,6 +15,7 @@ from note.api.urls import register_note_urls | ||||
| from treasury.api.urls import register_treasury_urls | ||||
| from logs.api.urls import register_logs_urls | ||||
| from permission.api.urls import register_permission_urls | ||||
| from wei.api.urls import register_wei_urls | ||||
|  | ||||
|  | ||||
| class UserSerializer(serializers.ModelSerializer): | ||||
| @@ -78,6 +79,7 @@ register_note_urls(router, 'note') | ||||
| register_treasury_urls(router, 'treasury') | ||||
| register_permission_urls(router, 'permission') | ||||
| register_logs_urls(router, 'logs') | ||||
| register_wei_urls(router, 'wei') | ||||
|  | ||||
| app_name = 'api' | ||||
|  | ||||
|   | ||||
							
								
								
									
										0
									
								
								apps/wei/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								apps/wei/api/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										17
									
								
								apps/wei/api/serializers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								apps/wei/api/serializers.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from rest_framework import serializers | ||||
|  | ||||
| from ..models import WEIClub | ||||
|  | ||||
|  | ||||
| class WEIClubSerializer(serializers.ModelSerializer): | ||||
|     """ | ||||
|     REST API Serializer for Clubs. | ||||
|     The djangorestframework plugin will analyse the model `WEIClub` and parse all fields in the API. | ||||
|     """ | ||||
|  | ||||
|     class Meta: | ||||
|         model = WEIClub | ||||
|         fields = '__all__' | ||||
							
								
								
									
										11
									
								
								apps/wei/api/urls.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								apps/wei/api/urls.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from .views import WEIClubViewSet | ||||
|  | ||||
|  | ||||
| def register_wei_urls(router, path): | ||||
|     """ | ||||
|     Configure router for Member REST API. | ||||
|     """ | ||||
|     router.register(path + '/club', WEIClubViewSet) | ||||
							
								
								
									
										20
									
								
								apps/wei/api/views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								apps/wei/api/views.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from rest_framework.filters import SearchFilter | ||||
| from api.viewsets import ReadProtectedModelViewSet | ||||
|  | ||||
| from .serializers import WEIClubSerializer | ||||
| from ..models import WEIClub | ||||
|  | ||||
|  | ||||
| class WEIClubViewSet(ReadProtectedModelViewSet): | ||||
|     """ | ||||
|     REST API View set. | ||||
|     The djangorestframework plugin will get all `WEIClub` objects, serialize it to JSON with the given serializer, | ||||
|     then render it on /api/wei/club/ | ||||
|     """ | ||||
|     queryset = WEIClub.objects.all() | ||||
|     serializer_class = WEIClubSerializer | ||||
|     filter_backends = [SearchFilter] | ||||
|     search_fields = ['$name', ] | ||||
							
								
								
									
										76
									
								
								apps/wei/fixtures/initial.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								apps/wei/fixtures/initial.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| [ | ||||
| 	{ | ||||
| 		"model": "member.club", | ||||
| 		"pk": 3, | ||||
| 		"fields": { | ||||
| 			"name": "A[WEI] from Home", | ||||
| 			"email": "gc.wei@example.com", | ||||
| 			"parent_club": 2, | ||||
| 			"require_memberships": true, | ||||
| 			"membership_fee_paid": 16500, | ||||
| 			"membership_fee_unpaid": 9500, | ||||
| 			"membership_duration": 30, | ||||
| 			"membership_start": "2019-09-01", | ||||
| 			"membership_end": "2019-09-16" | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		"model": "wei.weiclub", | ||||
| 		"pk": 1, | ||||
| 		"fields": { | ||||
| 			"club_ptr_id": 3, | ||||
| 			"year": 2019, | ||||
| 			"date_start": "2019-09-14", | ||||
| 			"date_end": "2019-09-16" | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		"model": "note.note", | ||||
| 		"pk": 7, | ||||
| 		"fields": { | ||||
| 			"polymorphic_ctype": [ | ||||
| 				"note", | ||||
| 				"noteclub" | ||||
| 			], | ||||
| 			"balance": 0, | ||||
| 			"last_negative": null, | ||||
| 			"is_active": true, | ||||
| 			"display_image": "pic/default.png", | ||||
| 			"created_at": "2020-02-20T20:16:14.753Z" | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		"model": "note.noteclub", | ||||
| 		"pk": 7, | ||||
| 		"fields": { | ||||
| 			"club": 3 | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		"model": "note.alias", | ||||
| 		"pk": 7, | ||||
| 		"fields": { | ||||
| 			"name": "A[WEI] from Home", | ||||
| 			"normalized_name": "aweifromhome", | ||||
| 			"note": 7 | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		"model": "note.alias", | ||||
| 		"pk": 8, | ||||
| 		"fields": { | ||||
| 			"name": "WEI 2019", | ||||
| 			"normalized_name": "wei2019", | ||||
| 			"note": 7 | ||||
| 		} | ||||
| 	}, | ||||
| 	{ | ||||
| 		"model": "note.alias", | ||||
| 		"pk": 9, | ||||
| 		"fields": { | ||||
| 			"name": "WEI", | ||||
| 			"normalized_name": "wei", | ||||
| 			"note": 7 | ||||
| 		} | ||||
| 	} | ||||
| ] | ||||
| @@ -1,23 +1,32 @@ | ||||
| # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| import json | ||||
|  | ||||
| from django.contrib.auth.models import User | ||||
| from django.db import models | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
|  | ||||
| from member.models import Role, Club, Membership | ||||
| from note.models import NoteSpecial | ||||
|  | ||||
|  | ||||
| class WEIClub(Club): | ||||
|     """ | ||||
|     The WEI is a club. Register to the WEI is equivalent than be member of the club. | ||||
|     """ | ||||
|     year = models.PositiveIntegerField( | ||||
|         unique=True, | ||||
|         verbose_name=_("year"), | ||||
|     ) | ||||
|  | ||||
|     date_start = models.DateField( | ||||
|         verbose_name=_("date start"), | ||||
|     ) | ||||
|  | ||||
|     date_end = models.DateField( | ||||
|         verbose_name=_("date end"), | ||||
|     ) | ||||
|  | ||||
|     def update_membership_dates(self): | ||||
|         """ | ||||
|         We can't join the WEI next years. | ||||
| @@ -84,6 +93,8 @@ class WEIRole(Role): | ||||
|     bus = models.ForeignKey( | ||||
|         Bus, | ||||
|         on_delete=models.CASCADE, | ||||
|         null=True, | ||||
|         default=None, | ||||
|         related_name="roles", | ||||
|         verbose_name=_("bus"), | ||||
|     ) | ||||
|   | ||||
							
								
								
									
										25
									
								
								apps/wei/tables.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								apps/wei/tables.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| import django_tables2 as tables | ||||
| from django.urls import reverse_lazy | ||||
|  | ||||
| from wei.models import WEIClub | ||||
|  | ||||
|  | ||||
| class WEITable(tables.Table): | ||||
|     """ | ||||
|     List all clubs. | ||||
|     """ | ||||
|     class Meta: | ||||
|         attrs = { | ||||
|             'class': 'table table-condensed table-striped table-hover' | ||||
|         } | ||||
|         model = WEIClub | ||||
|         template_name = 'django_tables2/bootstrap4.html' | ||||
|         fields = ('name', 'year', 'date_start', 'date_end',) | ||||
|         row_attrs = { | ||||
|             'class': 'table-row', | ||||
|             'id': lambda record: "row-" + str(record.pk), | ||||
|             'data-href': lambda record: reverse_lazy('member:club_detail', args=(record.pk,)) | ||||
|         } | ||||
| @@ -3,7 +3,10 @@ | ||||
|  | ||||
| from django.urls import path | ||||
|  | ||||
| from .views import WEIListView | ||||
|  | ||||
|  | ||||
| app_name = 'wei' | ||||
| urlpatterns = [ | ||||
|     path('list/', WEIListView.as_view(), name="wei_list"), | ||||
| ] | ||||
|   | ||||
| @@ -1,5 +1,17 @@ | ||||
| # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| from django.shortcuts import render | ||||
| from django.contrib.auth.mixins import LoginRequiredMixin | ||||
| from django_tables2 import SingleTableView | ||||
| from permission.views import ProtectQuerysetMixin | ||||
| from wei.models import WEIClub | ||||
|  | ||||
| from .tables import WEITable | ||||
|  | ||||
|  | ||||
| class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): | ||||
|     """ | ||||
|     List existing WEI | ||||
|     """ | ||||
|     model = WEIClub | ||||
|     table_class = WEITable | ||||
|   | ||||
| @@ -312,7 +312,7 @@ function in_validate(id, validated) { | ||||
|     else | ||||
|         invalidity_reason = null; | ||||
|  | ||||
|     $("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳ ...</strong>"); | ||||
|     $("#validate_" + id).html("<i class='fa fa-spinner'></i>"); | ||||
|  | ||||
|     // Perform a PATCH request to the API in order to update the transaction | ||||
|     // If the user has insuffisent rights, an error message will appear | ||||
|   | ||||
| @@ -108,9 +108,12 @@ SPDX-License-Identifier: GPL-3.0-or-later | ||||
|                 {% endif %} | ||||
|                 {% if "treasury.invoice"|not_empty_model_change_list %} | ||||
|                     <li class="nav-item active"> | ||||
|                         <a class="nav-link" href="{% url 'treasury:invoice_list' %}"><i class="fa fa-money"></i>{% trans 'Treasury' %} </a> | ||||
|                         <a class="nav-link" href="{% url 'treasury:invoice_list' %}"><i class="fa fa-money"></i> {% trans 'Treasury' %}</a> | ||||
|                     </li> | ||||
|                 {% endif %} | ||||
|                 <li class="nav-item active"> | ||||
|                     <a class="nav-link" href="{% url 'wei:wei_list' %}"><i class="fa fa-bus"></i> {% trans 'WEI' %}</a> | ||||
|                 </li> | ||||
|             </ul> | ||||
|             <ul class="navbar-nav ml-auto"> | ||||
|                 {% if user.is_authenticated %} | ||||
|   | ||||
| @@ -43,8 +43,8 @@ | ||||
|             <dt class="col-xl-6"><a href="{% url 'member:club_alias' club.pk %}">{% trans 'aliases'|capfirst %}</a></dt> | ||||
|             <dd class="col-xl-6 text-truncate">{{ object.note.alias_set.all|join:", " }}</dd> | ||||
|  | ||||
|             <dt class="col-xl-3">{% trans 'email'|capfirst %}</dt> | ||||
|             <dd class="col-xl-9"><a href="mailto:{{ club.email }}">{{ club.email }}</a></dd> | ||||
|             <dt class="col-xl-4">{% trans 'email'|capfirst %}</dt> | ||||
|             <dd class="col-xl-8"><a href="mailto:{{ club.email }}">{{ club.email }}</a></dd> | ||||
|         </dl> | ||||
|     </div> | ||||
|     <div class="card-footer text-center"> | ||||
|   | ||||
							
								
								
									
										70
									
								
								templates/wei/weiclub_list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								templates/wei/weiclub_list.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| {% extends "base.html" %} | ||||
| {% load render_table from django_tables2 %} | ||||
| {% load i18n %} | ||||
| {% block content %} | ||||
| <div class="row justify-content-center mb-4"> | ||||
|     <div class="col-md-10 text-center"> | ||||
|         <h4> | ||||
|             {% trans "search WEI" %} | ||||
|         </h4> | ||||
|         <input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved()" id="search_field"/> | ||||
|         <hr> | ||||
|         <a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}">{% trans "Create WEI" %}</a> | ||||
|     </div> | ||||
| </div> | ||||
| <div class="row justify-content-center">    | ||||
|     <div class="col-md-10"> | ||||
|         <div class="card card-border shadow"> | ||||
|             <div class="card-header text-center"> | ||||
|                 <h5> {% trans "WEI listing "%}</h5> | ||||
|             </div> | ||||
|             <div class="card-body px-0 py-0" id="club_table"> | ||||
|                 {% render_table table %} | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| {% endblock %} | ||||
| {% block extrajavascript %} | ||||
| <script type="text/javascript"> | ||||
|  | ||||
| function getInfo() { | ||||
|     var asked = $("#search_field").val(); | ||||
|     /* on ne fait la requête que si on a au moins un caractère pour chercher */ | ||||
|     var sel = $(".table-row"); | ||||
|     if (asked.length >= 1) { | ||||
|         $.getJSON("/api/wei/club/?format=json&search="+asked, function(buttons){ | ||||
|             let selected_id = buttons.results.map((a => "#row-"+a.id)); | ||||
|             $(".table-row,"+selected_id.join()).show(); | ||||
|             $(".table-row").not(selected_id.join()).hide(); | ||||
|              | ||||
|         }); | ||||
|     }else{ | ||||
|         // show everything | ||||
|         $('table tr').show(); | ||||
|     }        | ||||
| } | ||||
| var timer; | ||||
| var timer_on; | ||||
| /* Fontion appelée quand le texte change (délenche le timer) */ | ||||
| function search_field_moved(secondfield) { | ||||
|     if (timer_on) { // Si le timer a déjà été lancé, on réinitialise le compteur. | ||||
|         clearTimeout(timer); | ||||
|         timer = setTimeout("getInfo(" + secondfield + ")", 300); | ||||
|     } | ||||
|     else { // Sinon, on le lance et on enregistre le fait qu'il tourne. | ||||
|         timer = setTimeout("getInfo(" + secondfield + ")", 300); | ||||
|         timer_on = true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // clickable row  | ||||
| $(document).ready(function($) { | ||||
|     $(".table-row").click(function() { | ||||
|         window.document.location = $(this).data("href"); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| </script> | ||||
| {% endblock %} | ||||
							
								
								
									
										2
									
								
								tox.ini
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tox.ini
									
									
									
									
									
								
							| @@ -30,7 +30,7 @@ deps = | ||||
|     pep8-naming | ||||
|     pyflakes | ||||
| commands = | ||||
|     flake8 apps/activity apps/api apps/logs apps/member apps/note apps/permission apps/treasury | ||||
|     flake8 apps/activity apps/api apps/logs apps/member apps/note apps/permission apps/treasury apps/wei | ||||
|  | ||||
| [flake8] | ||||
| # Ignore too many errors, should be reduced in the future | ||||
|   | ||||
		Reference in New Issue
	
	Block a user