eo_redmine: first version (#83233)
so far it only allows filtering the client list, more to come
This commit is contained in:
parent
a588ee12ea
commit
5d7894bfab
|
@ -125,11 +125,44 @@ class ActiveFilter(admin.SimpleListFilter):
|
|||
return queryset.filter(active=bool(self.value() == 'True'))
|
||||
|
||||
|
||||
class MyClientsFilter(admin.SimpleListFilter):
|
||||
title = 'CPF'
|
||||
parameter_name = 'cpf'
|
||||
|
||||
def __init__(self, request, params, model, model_admin):
|
||||
super().__init__(request, params, model, model_admin)
|
||||
self.request = request
|
||||
|
||||
def value(self):
|
||||
from eo_gestion.eo_redmine.models import Project
|
||||
|
||||
value = super().value()
|
||||
default_value = 'all'
|
||||
user = self.request.user
|
||||
if user and Project.objects.filter(cpfs__contains=[user.username]).exists():
|
||||
default_value = 'True'
|
||||
|
||||
return value if value in ('True', 'all') else default_value
|
||||
|
||||
def choices(self, changelist):
|
||||
choices = list(super().choices(changelist))
|
||||
return choices[1:] # don't include automatic "All"
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
return [('all', 'tous'), ('True', 'mes clients')]
|
||||
|
||||
def queryset(self, request, queryset):
|
||||
if self.value() == 'True':
|
||||
return queryset.filter(project__cpfs__contains=[request.user.username])
|
||||
else:
|
||||
return queryset
|
||||
|
||||
|
||||
class ClientAdmin(admin.ModelAdmin):
|
||||
form = forms.ClientForm
|
||||
list_display = ['nom', 'adresse', 'email', 'telephone']
|
||||
list_editable = ['email', 'telephone']
|
||||
list_filter = [ActiveFilter]
|
||||
list_filter = [ActiveFilter, MyClientsFilter]
|
||||
ordering = ['nom']
|
||||
search_fields = ['nom', 'email']
|
||||
save_on_top = True
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
from django.contrib import admin
|
||||
|
||||
import eo_gestion.admin
|
||||
|
||||
from . import models
|
||||
|
||||
|
||||
class ProjectAdmin(admin.ModelAdmin):
|
||||
readonly_fields = ['name', 'cpfs']
|
||||
list_display = ['name', 'cpfs', 'client']
|
||||
|
||||
|
||||
admin.site.register(models.Project, ProjectAdmin)
|
||||
eo_gestion.admin.site.register(models.Project, ProjectAdmin)
|
|
@ -0,0 +1,77 @@
|
|||
import requests
|
||||
from django.conf import settings
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.db import transaction
|
||||
|
||||
from eo_gestion.eo_redmine.models import Project
|
||||
|
||||
REDMINE_HEADERS = {'X-Redmine-API-Key': settings.REDMINE_API_KEY}
|
||||
|
||||
|
||||
def redmine_iterator(base_url, entity_name):
|
||||
result = requests.get(base_url + '?limit=100', headers=REDMINE_HEADERS).json()
|
||||
total = 0
|
||||
while total < result['total_count']:
|
||||
for item in result[entity_name]:
|
||||
yield item
|
||||
total += 1
|
||||
if total < result['total_count']:
|
||||
result = requests.get(base_url + '?limit=100&offset=%s' % total, headers=REDMINE_HEADERS).json()
|
||||
|
||||
|
||||
redmine_user_cache = {}
|
||||
|
||||
|
||||
def redmine_get_login(user_id):
|
||||
if not user_id in redmine_user_cache:
|
||||
user_data = requests.get(
|
||||
settings.REDMINE_BASE_URL + 'users/%s.json' % user_id, headers=REDMINE_HEADERS
|
||||
).json()
|
||||
redmine_user_cache[user_id] = user_data['user']['login']
|
||||
return redmine_user_cache[user_id]
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@transaction.atomic
|
||||
def handle(self, *args, **options):
|
||||
alive_projects = []
|
||||
for project in redmine_iterator(settings.REDMINE_BASE_URL + 'projects.json', 'projects'):
|
||||
project_id = project['id']
|
||||
project_name = project['name']
|
||||
|
||||
# Skip inactive or non-client projects
|
||||
if project['status'] != 1:
|
||||
continue
|
||||
if not ('parent' in project) or project['parent']['name'] != 'Projets Clients':
|
||||
continue
|
||||
alive_projects.append(project_id)
|
||||
|
||||
# get the members
|
||||
cpf_ids = set()
|
||||
for membership in redmine_iterator(
|
||||
settings.REDMINE_BASE_URL + 'projects/%s/memberships.json' % project_id, 'memberships'
|
||||
):
|
||||
if not 'user' in membership:
|
||||
continue
|
||||
for role in membership['roles']:
|
||||
if role['name'] in ('CPF', 'CPF (Backup)'):
|
||||
cpf_ids.add(membership['user']['id'])
|
||||
cpfs = []
|
||||
for cpf_id in cpf_ids:
|
||||
cpfs.append(redmine_get_login(cpf_id))
|
||||
|
||||
# now match in our DB, maybe update
|
||||
insert = False
|
||||
try:
|
||||
project_object = Project.objects.get(id=project_id)
|
||||
except Project.DoesNotExist:
|
||||
project_object = Project()
|
||||
project_object.id = project_id
|
||||
insert = True
|
||||
|
||||
project_object.name = project_name
|
||||
project_object.cpfs = cpfs
|
||||
project_object.save(force_insert=insert)
|
||||
|
||||
# Purge dead projects
|
||||
Project.objects.exclude(id__in=alive_projects).delete()
|
|
@ -0,0 +1,38 @@
|
|||
# Generated by Django 3.2.21 on 2023-11-08 10:11
|
||||
|
||||
import django.contrib.postgres.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('eo_facture', '0019_alter_contrat_client'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Project',
|
||||
fields=[
|
||||
(
|
||||
'id',
|
||||
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
('name', models.CharField(max_length=255)),
|
||||
(
|
||||
'cpfs',
|
||||
django.contrib.postgres.fields.ArrayField(
|
||||
base_field=models.CharField(max_length=255), size=None
|
||||
),
|
||||
),
|
||||
(
|
||||
'client',
|
||||
models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.CASCADE, to='eo_facture.client'
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -0,0 +1,13 @@
|
|||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.db import models
|
||||
|
||||
from eo_gestion.eo_facture.models import Client
|
||||
|
||||
|
||||
class Project(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
cpfs = ArrayField(models.CharField(max_length=255))
|
||||
client = models.ForeignKey(Client, on_delete=models.CASCADE, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -0,0 +1,3 @@
|
|||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
|
@ -169,6 +169,7 @@ INSTALLED_APPS = (
|
|||
'eo_gestion.eo_facture',
|
||||
'eo_gestion.eo_banque',
|
||||
'eo_gestion.eo_conges',
|
||||
'eo_gestion.eo_redmine',
|
||||
'eo_gestion.chorus',
|
||||
'taggit',
|
||||
'adminsortable2',
|
||||
|
@ -207,6 +208,9 @@ WORKERS_CALENDAR_CONFIG = {
|
|||
],
|
||||
}
|
||||
|
||||
REDMINE_BASE_URL = 'https://dev.entrouvert.org/'
|
||||
REDMINE_API_KEY = ''
|
||||
|
||||
local_settings_file = os.environ.get('BARBACOMPTA_SETTINGS_FILE', 'local_settings.py')
|
||||
if os.path.exists(local_settings_file):
|
||||
with open(local_settings_file) as fd:
|
||||
|
|
Loading…
Reference in New Issue