Browse Source

début des apps adhesions, banking & services

Élie Bouttier 8 years ago
parent
commit
866a1e97d3

+ 1 - 0
.gitignore

@@ -2,4 +2,5 @@
 *.pyc
 *.swp
 *.sqlite3
+*.back
 djadhere/*_settings.py

+ 1 - 0
adhesions/__init__.py

@@ -0,0 +1 @@
+default_app_config = 'adhesions.apps.AdhesionsConfig'

+ 40 - 0
adhesions/admin.py

@@ -0,0 +1,40 @@
+from django.contrib import admin
+
+from .models import Profile, Corporation, Adherent
+
+
+class ProfileAdmin(admin.ModelAdmin):
+    list_display = ('user', 'phone_number',)
+
+
+class AdherentTypeFilter(admin.SimpleListFilter):
+    title = 'type d’adhérent'
+    parameter_name = 'type'
+
+    def lookups(self, request, model_admin):
+        return (
+            ('physique', 'Personne physique'),
+            ('morale', 'Personne morale'),
+        )
+
+    def queryset(self, request, queryset):
+        if self.value() == 'physique':
+            return queryset.filter(adherent_type__app_label='auth',
+                                   adherent_type__model='user')
+        if self.value() == 'morale':
+            return queryset.filter(adherent_type__app_label='adhesions',
+                                   adherent_type__model='corporation')
+
+
+class AdherentAdmin(admin.ModelAdmin):
+    list_display = ('id', 'adherent_name', 'type',)
+    list_filter = (AdherentTypeFilter,)
+
+    def adherent_name(self, obj):
+        return str(obj)
+    adherent_name.short_description = 'Nom ou raison sociale'
+
+
+admin.site.register(Profile, ProfileAdmin)
+admin.site.register(Corporation)
+admin.site.register(Adherent, AdherentAdmin)

+ 9 - 0
adhesions/apps.py

@@ -0,0 +1,9 @@
+from django.apps import AppConfig
+
+
+class AdhesionsConfig(AppConfig):
+    name = 'adhesions'
+    verbose_name = 'adhésions'
+
+    def ready(self):
+        import adhesions.signals

+ 59 - 0
adhesions/migrations/0001_initial.py

@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.4 on 2016-12-30 02:58
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('banking', '0001_initial'),
+        ('contenttypes', '0002_remove_content_type_name'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Adherent',
+            fields=[
+                ('id', models.IntegerField(primary_key=True, serialize=False, verbose_name='Numéro d’adhérent')),
+                ('adherent_id', models.PositiveIntegerField(verbose_name='ID')),
+                ('adherent_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='Type d’adhérent')),
+                ('contribution', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='adherent', to='banking.Payment')),
+            ],
+            options={
+                'verbose_name': 'adhérent',
+            },
+        ),
+        migrations.CreateModel(
+            name='Corporation',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('social_reason', models.CharField(max_length=256, verbose_name='Raison sociale')),
+                ('description', models.TextField(blank=True, default='')),
+                ('address', models.TextField(blank=True, default='', verbose_name='Adresse')),
+                ('members', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Membres')),
+            ],
+            options={
+                'verbose_name_plural': 'personnes morales',
+                'verbose_name': 'personne morale',
+            },
+        ),
+        migrations.CreateModel(
+            name='Profile',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('phone_number', models.CharField(blank=True, default='', max_length=16, verbose_name='Numéro de téléphone')),
+                ('address', models.TextField(blank=True, default='', verbose_name='Adresse')),
+                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL, verbose_name='Utilisateur')),
+            ],
+            options={
+                'verbose_name': 'profil',
+            },
+        ),
+    ]

+ 0 - 0
adhesions/migrations/__init__.py


+ 58 - 0
adhesions/models.py

@@ -0,0 +1,58 @@
+from django.db import models
+from django.contrib.auth.models import User
+from django.contrib.contenttypes.fields import GenericForeignKey
+from django.contrib.contenttypes.models import ContentType
+
+
+from banking.models import Payment
+
+
+class Profile(models.Model):
+    user = models.OneToOneField(User, related_name='profile', verbose_name='Utilisateur')
+    phone_number = models.CharField(max_length=16, blank=True, default='',
+                                    verbose_name='Numéro de téléphone')
+    address = models.TextField(blank=True, default='', verbose_name='Adresse')
+
+    class Meta:
+        verbose_name = 'profil'
+
+    def __str__(self):
+        return 'Profil de %s' % self.user
+
+
+class Corporation(models.Model):
+    social_reason = models.CharField(max_length=256, verbose_name='Raison sociale')
+    description = models.TextField(blank=True, default='')
+    address = models.TextField(blank=True, default='', verbose_name='Adresse')
+    members = models.ManyToManyField(User, blank=True, verbose_name='Membres')
+
+    class Meta:
+        verbose_name = 'personne morale'
+        verbose_name_plural = 'personnes morales'
+
+    def __str__(self):
+        return self.social_reason
+
+
+class Adherent(models.Model):
+    limit = models.Q(app_label='auth', model='user') | models.Q(app_label='adhesions', model='corporation')
+    id = models.IntegerField(verbose_name='Numéro d’adhérent', primary_key=True)
+    adherent_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
+                                      limit_choices_to=limit, verbose_name='Type d’adhérent')
+    adherent_id = models.PositiveIntegerField(verbose_name='ID')
+    adherent = GenericForeignKey('adherent_type', 'adherent_id')
+    contribution = models.ForeignKey(Payment, on_delete=models.CASCADE,
+                                     related_name='adherent', null=True, blank=True)
+
+    class Meta:
+        verbose_name = 'adhérent'
+
+    @property
+    def type(self):
+        if self.adherent_type.app_label == 'auth' and self.adherent_type.model == 'user':
+            return 'Personne physique'
+        else:
+            return 'Personne morale'
+
+    def __str__(self):
+        return str(self.adherent)

+ 11 - 0
adhesions/signals.py

@@ -0,0 +1,11 @@
+from django.dispatch import receiver
+from django.db.models.signals import post_save
+from django.contrib.auth.models import User
+
+from .models import Profile
+
+
+@receiver(post_save, sender=User, dispatch_uid='create_profile')
+def create_profile(sender, instance, created, **kwargs):
+    if created:
+        Profile.objects.create(user=instance)

+ 3 - 0
adhesions/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 3 - 0
adhesions/views.py

@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.

+ 1 - 0
banking/__init__.py

@@ -0,0 +1 @@
+default_app_config = 'banking.apps.BankingConfig'

+ 11 - 0
banking/admin.py

@@ -0,0 +1,11 @@
+from django.contrib import admin
+
+from .models import Payment
+
+
+class PaymentAdmin(admin.ModelAdmin):
+    list_display = ('adherent', 'amount', 'period', 'payment_method',)
+    list_filter = ('payment_method',)
+
+
+admin.site.register(Payment, PaymentAdmin)

+ 6 - 0
banking/apps.py

@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class BankingConfig(AppConfig):
+    name = 'banking'
+    verbose_name = 'Comptabilité'

+ 29 - 0
banking/migrations/0001_initial.py

@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.4 on 2016-12-30 02:58
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Payment',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('amount', models.DecimalField(decimal_places=2, max_digits=9, verbose_name='Montant')),
+                ('period', models.PositiveIntegerField(validators=[django.core.validators.MaxValueValidator(12)], verbose_name='Période')),
+                ('payment_method', models.IntegerField(choices=[(0, 'Virement'), (1, 'Prélèvement')], verbose_name='Méthode de paiement')),
+            ],
+            options={
+                'verbose_name': 'paiement',
+            },
+        ),
+    ]

+ 0 - 0
banking/migrations/__init__.py


+ 27 - 0
banking/models.py

@@ -0,0 +1,27 @@
+from django.db import models
+from django.core.validators import MaxValueValidator
+
+
+class Payment(models.Model):
+    TRANSFERT = 0 
+    WITHDRAWAL = 1 
+    PAYMENT_CHOICES = ( 
+        (TRANSFERT, 'Virement'),
+        (WITHDRAWAL, 'Prélèvement'),
+    )   
+    amount = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Montant')
+    period = models.PositiveIntegerField(validators=[MaxValueValidator(12)], verbose_name='Période')
+    payment_method = models.IntegerField(choices=PAYMENT_CHOICES, verbose_name='Méthode de paiement')
+
+    class Meta:
+        verbose_name = 'paiement'
+
+    def __str__(self):
+        s = str(self.amount) + '€' 
+        if self.period:
+            s += '%d/mois' % self.period
+        if self.payment_method == self.TRANSFERT:
+            s += ' (virement)'
+        elif self.payment_method == self.WITHDRAWAL:
+            s += ' (prélèvement)'
+        return s

+ 3 - 0
banking/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 3 - 0
banking/views.py

@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.

+ 6 - 2
djadhere/settings.py

@@ -31,6 +31,10 @@ ALLOWED_HOSTS = []
 # Application definition
 
 INSTALLED_APPS = [
+    'adhesions',
+    'services',
+    'banking',
+    'djadhere',
     'django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
@@ -103,9 +107,9 @@ AUTH_PASSWORD_VALIDATORS = [
 # Internationalization
 # https://docs.djangoproject.com/en/1.10/topics/i18n/
 
-LANGUAGE_CODE = 'en-us'
+LANGUAGE_CODE = 'fr-FR'
 
-TIME_ZONE = 'UTC'
+TIME_ZONE = 'Europe/Paris'
 
 USE_I18N = True
 

+ 1 - 0
services/__init__.py

@@ -0,0 +1 @@
+default_app_config = 'services.apps.ServicesConfig'

+ 78 - 0
services/admin.py

@@ -0,0 +1,78 @@
+from django.contrib import admin
+from django.db.models import Q
+from django.utils import timezone
+
+from .models import Service, ServiceType, IPResource
+
+
+class ServiceTypeFilter(admin.SimpleListFilter):
+    title = 'type de service'
+    parameter_name = 'type'
+
+    def lookups(self, request, model_admin):
+        return ServiceType.objects.all().values_list('pk', 'name')
+
+    def queryset(self, request, queryset):
+        if self.value():
+            return queryset.filter(service_type__pk=self.value())
+
+
+class ServiceStatusFilter(admin.SimpleListFilter):
+    title = 'status du service'
+    parameter_name = 'status'
+
+    def lookups(self, request, model_admin):
+        return (
+            ('ongoing', 'En cours'),
+            ('finished', 'Terminé'),
+        )
+
+    def queryset(self, request, queryset):
+        if self.value() == 'ongoing':
+            return queryset.filter(end__isnull=True)
+        if self.value() == 'finished':
+            return queryset.filter(end__isnull=False)
+
+
+class ServiceAdmin(admin.ModelAdmin):
+    list_display = ('id', 'adherent', 'service_type', 'start', 'end_view',)
+    list_filter = (ServiceStatusFilter, ServiceTypeFilter,)
+
+    def end_view(self, obj):
+        return obj.end
+    end_view.short_description = 'Fin du service'
+    end_view.empty_value_display = 'Service en cours'
+
+
+class InUseFilter(admin.SimpleListFilter):
+    title = 'disponibilité'
+    parameter_name = 'available'
+
+    def lookups(self, request, model_admin):
+        return (
+            (1, 'Disponible'),
+            (0, 'Non disponible'),
+        )
+
+    def queryset(self, request, queryset):
+        in_use_filter = Q(service__start__gte=timezone.now()) \
+                | Q(service__end__isnull=True)
+        if self.value() == '0':
+            return queryset.filter(in_use_filter)
+        if self.value() == '1':
+            return queryset.exclude(in_use_filter)
+
+
+class IPResourceAdmin(admin.ModelAdmin):
+    list_display = ('__str__', 'in_use_view')
+    list_filter = (InUseFilter,)
+
+    def in_use_view(self, obj):
+        return not obj.in_use
+    in_use_view.short_description = 'Disponible'
+    in_use_view.boolean = True
+
+
+admin.site.register(Service, ServiceAdmin)
+admin.site.register(ServiceType)
+admin.site.register(IPResource, IPResourceAdmin)

+ 5 - 0
services/apps.py

@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class ServicesConfig(AppConfig):
+    name = 'services'

+ 60 - 0
services/migrations/0001_initial.py

@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.4 on 2016-12-30 02:58
+from __future__ import unicode_literals
+
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('banking', '0001_initial'),
+        ('adhesions', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='IPResource',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('ip', models.GenericIPAddressField()),
+                ('mask', models.PositiveIntegerField(default=0, validators=[django.core.validators.MaxValueValidator(128)])),
+            ],
+            options={
+                'verbose_name_plural': 'Ressources IP',
+                'verbose_name': 'Ressource IP',
+            },
+        ),
+        migrations.CreateModel(
+            name='Service',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('notes', models.TextField(blank=True, default='')),
+                ('start', models.DateTimeField(verbose_name='Début du service')),
+                ('end', models.DateTimeField(blank=True, null=True, verbose_name='Fin du service')),
+                ('adherent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='adhesions.Adherent', verbose_name='Adhérent')),
+                ('contribution', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='banking.Payment')),
+                ('ip_resources', models.ManyToManyField(to='services.IPResource', verbose_name='Ressources IP')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='ServiceType',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=64)),
+            ],
+            options={
+                'verbose_name_plural': 'Types de service',
+                'verbose_name': 'Type de service',
+            },
+        ),
+        migrations.AddField(
+            model_name='service',
+            name='service_type',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='services.ServiceType', verbose_name='Type de service'),
+        ),
+    ]

+ 0 - 0
services/migrations/__init__.py


+ 61 - 0
services/models.py

@@ -0,0 +1,61 @@
+from django.db import models
+from django.core.validators import MaxValueValidator
+from django.utils import timezone
+
+from adhesions.models import Adherent
+from banking.models import Payment
+
+
+class IPResource(models.Model):
+    ip = models.GenericIPAddressField()
+    mask = models.PositiveIntegerField(validators=[MaxValueValidator(128)], default=0)
+
+    @property
+    def in_use(self):
+        if Service.objects.filter(ip_resources=self, start__lte=timezone.now(),
+                                  end__isnull=True).exists():
+            return True
+        else:
+            return False
+
+    class Meta:
+        verbose_name = 'Ressource IP'
+        verbose_name_plural = 'Ressources IP'
+
+    def __str__(self):
+        r = str(self.ip)
+        if self.mask:
+            r += '/%d' % self.mask
+        return r
+
+
+class ServiceType(models.Model):
+    name = models.CharField(max_length=64)
+
+    class Meta:
+        verbose_name = 'Type de service'
+        verbose_name_plural = 'Types de service'
+
+    def __str__(self):
+        return self.name
+
+
+class Service(models.Model):
+    adherent = models.ForeignKey(Adherent, verbose_name='Adhérent')
+    service_type = models.ForeignKey(ServiceType, verbose_name='Type de service')
+    notes = models.TextField(blank=True, default='')
+    contribution = models.ForeignKey(Payment, null=True, blank=True)
+    ip_resources = models.ManyToManyField(IPResource,
+                                          verbose_name='Ressources IP')
+    start = models.DateTimeField(verbose_name='Début du service')
+    end = models.DateTimeField(null=True, blank=True, verbose_name='Fin du service')
+
+    @property
+    def status(self):
+        if self.end:
+            return 'Terminé le %s' % self.end
+        else:
+            return 'En cours'
+
+    def __str__(self):
+        return str(self.service_type) + ' ' + str(self.adherent)

+ 3 - 0
services/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 3 - 0
services/views.py

@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.