mirror of
				https://gitlab.crans.org/bde/nk20
				synced 2025-10-31 15:50:03 +01:00 
			
		
		
		
	Merge branch 'master' into 'fix-what-i-broke'
# Conflicts: # templates/base.html
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| [submodule "apps/scripts"] | ||||
| 	path = apps/scripts | ||||
| 	url = git@gitlab.crans.org:bde/nk20-scripts.git | ||||
| @@ -46,6 +46,7 @@ class Profile(models.Model): | ||||
|     class Meta: | ||||
|         verbose_name = _('user profile') | ||||
|         verbose_name_plural = _('user profile') | ||||
|         indexes = [ models.Index(fields=['user']) ] | ||||
|  | ||||
|     def get_absolute_url(self): | ||||
|         return reverse('user_detail', args=(self.pk,)) | ||||
| @@ -152,6 +153,7 @@ class Membership(models.Model): | ||||
|     class Meta: | ||||
|         verbose_name = _('membership') | ||||
|         verbose_name_plural = _('memberships') | ||||
|         indexes = [ models.Index(fields=['user']) ] | ||||
|  | ||||
| # @receiver(post_save, sender=settings.AUTH_USER_MODEL) | ||||
| # def save_user_profile(instance, created, **_kwargs): | ||||
|   | ||||
| @@ -6,7 +6,7 @@ from django import forms | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
|  | ||||
| from .models import Alias | ||||
| from .models import Transaction, TransactionTemplate, TemplateTransaction | ||||
| from .models import Transaction, TransactionTemplate | ||||
|  | ||||
|  | ||||
| class AliasForm(forms.ModelForm): | ||||
| @@ -99,33 +99,3 @@ class TransactionForm(forms.ModelForm): | ||||
|                     }, | ||||
|                 ), | ||||
|         } | ||||
|  | ||||
|  | ||||
| class ConsoForm(forms.ModelForm): | ||||
|     def save(self, commit=True): | ||||
|         button: TransactionTemplate = TransactionTemplate.objects.filter( | ||||
|             name=self.data['button']).get() | ||||
|         self.instance.destination = button.destination | ||||
|         self.instance.amount = button.amount | ||||
|         self.instance.reason = '{} ({})'.format(button.name, button.category) | ||||
|         self.instance.template = button | ||||
|         self.instance.category = button.category | ||||
|         super().save(commit) | ||||
|  | ||||
|     class Meta: | ||||
|         model = TemplateTransaction | ||||
|         fields = ('source',) | ||||
|  | ||||
|         # Le champ d'utilisateur est remplacé par un champ d'auto-complétion. | ||||
|         # Quand des lettres sont tapées, une requête est envoyée sur l'API d'auto-complétion | ||||
|         # et récupère les aliases de note valides | ||||
|         widgets = { | ||||
|             'source': | ||||
|                 autocomplete.ModelSelect2( | ||||
|                     url='note:note_autocomplete', | ||||
|                     attrs={ | ||||
|                         'data-placeholder': 'Note ...', | ||||
|                         'data-minimum-input-length': 1, | ||||
|                     }, | ||||
|                 ), | ||||
|         } | ||||
|   | ||||
| @@ -209,6 +209,10 @@ class Alias(models.Model): | ||||
|     class Meta: | ||||
|         verbose_name = _("alias") | ||||
|         verbose_name_plural = _("aliases") | ||||
|         indexes = [ | ||||
|             models.Index(fields=['name']), | ||||
|             models.Index(fields=['normalized_name']), | ||||
|         ] | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|   | ||||
| @@ -119,6 +119,11 @@ class Transaction(PolymorphicModel): | ||||
|     class Meta: | ||||
|         verbose_name = _("transaction") | ||||
|         verbose_name_plural = _("transactions") | ||||
|         indexes = [ | ||||
|             models.Index(fields=['created_at']), | ||||
|             models.Index(fields=['source']), | ||||
|             models.Index(fields=['destination']), | ||||
|         ] | ||||
|  | ||||
|     def save(self, *args, **kwargs): | ||||
|         """ | ||||
|   | ||||
| @@ -7,9 +7,11 @@ from django.db.models import Q | ||||
| from django.urls import reverse | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from django.views.generic import CreateView, ListView, UpdateView | ||||
| from django_tables2 import SingleTableView | ||||
|  | ||||
| from .forms import TransactionForm, TransactionTemplateForm, ConsoForm | ||||
| from .models import Transaction, TransactionTemplate, Alias, TemplateTransaction | ||||
| from .forms import TransactionForm, TransactionTemplateForm | ||||
| from .models import Transaction, TransactionTemplate, Alias | ||||
| from .tables import HistoryTable | ||||
|  | ||||
|  | ||||
| class TransactionCreate(LoginRequiredMixin, CreateView): | ||||
| @@ -121,13 +123,16 @@ class TransactionTemplateUpdateView(LoginRequiredMixin, UpdateView): | ||||
|     form_class = TransactionTemplateForm | ||||
|  | ||||
|  | ||||
| class ConsoView(LoginRequiredMixin, CreateView): | ||||
| class ConsoView(LoginRequiredMixin, SingleTableView): | ||||
|     """ | ||||
|     Consume | ||||
|     """ | ||||
|     model = TemplateTransaction | ||||
|     model = Transaction | ||||
|     template_name = "note/conso_form.html" | ||||
|     form_class = ConsoForm | ||||
|  | ||||
|     # Transaction history table | ||||
|     table_class = HistoryTable | ||||
|     table_pagination = {"per_page": 10} | ||||
|  | ||||
|     def get_context_data(self, **kwargs): | ||||
|         """ | ||||
| @@ -142,9 +147,3 @@ class ConsoView(LoginRequiredMixin, CreateView): | ||||
|         context['no_cache'] = True | ||||
|  | ||||
|         return context | ||||
|  | ||||
|     def get_success_url(self): | ||||
|         """ | ||||
|         When clicking a button, reload the same page | ||||
|         """ | ||||
|         return reverse('note:consos') | ||||
|   | ||||
							
								
								
									
										1
									
								
								apps/scripts
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								apps/scripts
									
									
									
									
									
										Submodule
									
								
							 Submodule apps/scripts added at 123466cfa9
									
								
							| @@ -1,80 +1,134 @@ | ||||
| {% extends "base.html" %} | ||||
|  | ||||
| {% load i18n static pretty_money %} | ||||
| {% load i18n static pretty_money django_tables2 %} | ||||
|  | ||||
| {# Remove page title #} | ||||
| {% block contenttitle %}{% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|     {# Regroup buttons under categories #} | ||||
|     {% regroup transaction_templates by category as categories %} | ||||
|  | ||||
|     <form method="post" onsubmit="window.onbeforeunload=null"> | ||||
|         {% csrf_token %} | ||||
|  | ||||
|         <div class="row"> | ||||
|             <div class="col-sm-5 mb-4"> | ||||
|                 {% if form.non_field_errors %} | ||||
|                     <p class="errornote"> | ||||
|                         {% for error in form.non_field_errors %} | ||||
|                             {{ error }} | ||||
|                         {% endfor %} | ||||
|                     </p> | ||||
|                 {% endif %} | ||||
|                 {% for field in form %} | ||||
|                     <div class="form-row{% if field.errors %} errors{% endif %}"> | ||||
|                         {{ field.errors }} | ||||
|                         <div> | ||||
|                             {{ field.label_tag }} | ||||
|                             {% if field.is_readonly %} | ||||
|                                 <div class="readonly">{{ field.contents }}</div> | ||||
|                             {% else %} | ||||
|                                 {{ field }} | ||||
|                             {% endif %} | ||||
|                             {% if field.field.help_text %} | ||||
|                                 <div class="help">{{ field.field.help_text|safe }}</div> | ||||
|                             {% endif %} | ||||
|     <div class="row mt-4"> | ||||
|         <div class="col-sm-5 col-md-4"> | ||||
|             <div class="row"> | ||||
|                 {# User details column #} | ||||
|                 <div class="col-xl-5"> | ||||
|                     <div class="card border-success shadow mb-4"> | ||||
|                         <img src="https://perso.crans.org/erdnaxe/site-crans/img/logo.svg" | ||||
|                             alt="" class="img-fluid rounded mx-auto d-block"> | ||||
|                         <div class="card-body text-center"> | ||||
|                             Paquito (aka. PAC) : -230 € | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 {% endfor %} | ||||
|             </div> | ||||
|                 </div> | ||||
|  | ||||
|             <div class="col-sm-7"> | ||||
|                 <div class="card text-center shadow"> | ||||
|                     {# Tabs for button categories #} | ||||
|                     <div class="card-header"> | ||||
|                         <ul class="nav nav-tabs nav-fill card-header-tabs"> | ||||
|                             {% for category in categories %} | ||||
|                                 <li class="nav-item"> | ||||
|                                     <a class="nav-link" data-toggle="tab" href="#{{ category.grouper|slugify }}"> | ||||
|                                         {{ category.grouper }} | ||||
|                                     </a> | ||||
|                                 </li> | ||||
|                             {% endfor %} | ||||
|                 {# User selection column #} | ||||
|                 <div class="col-xl-7"> | ||||
|                     <div class="card border-success shadow mb-4"> | ||||
|                         <div class="card-header"> | ||||
|                             <p class="card-text font-weight-bold"> | ||||
|                                 Sélection des émitteurs | ||||
|                             </p> | ||||
|                         </div> | ||||
|                         <ul class="list-group list-group-flush"> | ||||
|                             <li class="list-group-item py-1 d-flex justify-content-between align-items-center"> | ||||
|                                 Cras justo odio | ||||
|                                 <span class="badge badge-dark badge-pill">14</span> | ||||
|                             </li> | ||||
|                             <li class="list-group-item py-1 d-flex justify-content-between align-items-center"> | ||||
|                                 Dapibus ac facilisis in | ||||
|                                 <span class="badge badge-dark badge-pill">1</span> | ||||
|                             </li> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|  | ||||
|                     {# Tabs content #} | ||||
|                     <div class="card-body"> | ||||
|                         <div class="tab-content"> | ||||
|                             {% for category in categories %} | ||||
|                                 <div class="tab-pane" id="{{ category.grouper|slugify }}"> | ||||
|                                     <div class="d-inline-flex flex-wrap justify-content-center"> | ||||
|                                         {% for button in category.list %} | ||||
|                                             <button class="btn btn-outline-dark rounded-0 flex-fill" | ||||
|                                                     name="button" value="{{ button.name }}"> | ||||
|                                                 {{ button.name }} ({{ button.amount | pretty_money }}) | ||||
|                                             </button> | ||||
|                                         {% endfor %} | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             {% endfor %} | ||||
|                         <div class="card-body"> | ||||
|                             TODO: reimplement select2 here in JS | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </form> | ||||
|  | ||||
|         {# Buttons column #} | ||||
|         <div class="col-sm-7 col-md-8"> | ||||
|             {# Show last used buttons #} | ||||
|             <div class="card shadow mb-4"> | ||||
|                 <div class="card-body text-nowrap" style="overflow:auto hidden"> | ||||
|                     <p class="card-text text-muted font-weight-light font-italic"> | ||||
|                         Les boutons les plus utilisés s'afficheront ici. | ||||
|                     </p> | ||||
|                 </div> | ||||
|             </div> | ||||
|  | ||||
|             {# Regroup buttons under categories #} | ||||
|             {% regroup transaction_templates by template_type as template_types %} | ||||
|  | ||||
|             <div class="card border-primary text-center shadow mb-4"> | ||||
|                 {# Tabs for button categories #} | ||||
|                 <div class="card-header"> | ||||
|                     <ul class="nav nav-tabs nav-fill card-header-tabs"> | ||||
|                         {% for template_type in template_types %} | ||||
|                             <li class="nav-item"> | ||||
|                                 <a class="nav-link font-weight-bold" data-toggle="tab" href="#{{ template_type.grouper|slugify }}"> | ||||
|                                     {{ template_type.grouper }} | ||||
|                                 </a> | ||||
|                             </li> | ||||
|                         {% endfor %} | ||||
|                     </ul> | ||||
|                 </div> | ||||
|  | ||||
|                 {# Tabs content #} | ||||
|                 <div class="card-body"> | ||||
|                     <div class="tab-content"> | ||||
|                         {% for template_type in template_types %} | ||||
|                             <div class="tab-pane" id="{{ template_type.grouper|slugify }}"> | ||||
|                                 <div class="d-inline-flex flex-wrap justify-content-center"> | ||||
|                                     {% for button in template_type.list %} | ||||
|                                         <button class="btn btn-outline-dark rounded-0 flex-fill" | ||||
|                                                 name="button" value="{{ button.name }}"> | ||||
|                                             {{ button.name }} ({{ button.amount | pretty_money }}) | ||||
|                                         </button> | ||||
|                                     {% endfor %} | ||||
|                                 </div> | ||||
|                             </div> | ||||
|                         {% endfor %} | ||||
|                     </div> | ||||
|                 </div> | ||||
|  | ||||
|                 {# Mode switch #} | ||||
|                 <div class="card-footer border-primary"> | ||||
|                     <a class="btn btn-sm btn-secondary float-left" href="{% url 'note:template_list' %}"> | ||||
|                         <i class="fa fa-edit"></i> Éditer | ||||
|                     </a> | ||||
|                     <div class="btn-group btn-group-toggle float-right" data-toggle="buttons"> | ||||
|                         <label class="btn btn-sm btn-outline-primary active"> | ||||
|                             <input type="radio" name="options" id="option1" checked> | ||||
|                             Consomations simples | ||||
|                         </label> | ||||
|                         <label class="btn btn-sm btn-outline-primary"> | ||||
|                             <input type="radio" name="options" id="option2"> | ||||
|                             Consomations doubles | ||||
|                         </label> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
|     <div class="card shadow mb-4"> | ||||
|         <div class="card-header"> | ||||
|             <p class="card-text font-weight-bold"> | ||||
|                 Historique des transactions récentes | ||||
|             </p> | ||||
|         </div> | ||||
|         {% render_table table %} | ||||
|     </div> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block extracss %} | ||||
|     <style> | ||||
|         .select2-container{ | ||||
|             max-width: 100%; | ||||
|             min-width: 100%; | ||||
|         } | ||||
|     </style> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block extrajavascript %} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user