Gestion de contact et suivi de conversion pour les groupement d'agriculture biologique
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1253 lines
38 KiB

# -*- coding: utf-8 -*-
import django.contrib.auth.admin as auth_admin
import django.contrib.auth.models as auth_models
import django.db as db
import django.forms as forms
from django.contrib import admin, messages
from django.forms.models import BaseInlineFormSet
from django.urls import reverse
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
import basket
import contacts.admin_forms as admin_forms
import contacts.admin_views as admv
import contacts.forms as contacts_forms
import contacts.models as contacts_models
# from contacts.settings_messages import AVERTISSEMENT_MESSAGE as w_msg
# Helper function
def get_readonly_field(model_admin):
"parse model_admin.fieldsets to set up a readonly mask"
rof = []
if model_admin.fieldsets:
for label, opt in model_admin.fieldsets:
for field in opt['fields']:
if isinstance(field, (tuple, list)):
rof.extend(field)
else:
rof.append(field)
elif model_admin.fields:
rof.extend(model_admin.fields)
return rof
def debug_admin(model_admin, request, queryset):
# import pdb; pdb.set_trace()
return
class PostSaveMsgMixin(object):
"send message to user after save_related()"
def save_related(self, request, form, formsets, change):
"get info/warning message"
super(PostSaveMsgMixin, self).save_related(
request, form, formsets, change
)
mlist = getattr(form.instance, 'get_messages', lambda x: [])
for msg in mlist():
messages.add_message(request, *msg)
class LookupAllowedMixin(object):
"""This class introduce lookup_allowed_tags in order to allow
complex lookup with admin.SimpleListFilter not beiing catch
by SuspiciousOperation"""
def lookup_allowed(self, key, value):
if self.lookup_allowed_tags and key in self.lookup_allowed_tags:
return True
return super(LookupAllowedMixin, self).lookup_allowed(key, value)
class UserFilter(admin.SimpleListFilter):
def lookups(self, request, models):
list_tech = (
contacts_models.AdhLogin.objects.annotate(
group_count=db.models.Count('groups')
)
.filter(is_active=True, group_count__gte=1)
.order_by('username')
)
return [(t.id, t.username) for t in list_tech]
def queryset(self, request, queryset):
val = self.value()
if val:
return queryset.filter(**{self.parameter_name: val})
return queryset
class TechnicienFilter(UserFilter):
title = 'technicien'
parameter_name = 'technicien__id__exact'
class ProjetBioTechnicienFilter(UserFilter):
title = 'projet bio suivi par'
parameter_name = 'projet_bio__technicien__id__exact'
# ## Admin des utilisateurs
class AdminUser(auth_admin.UserAdmin):
"""
On redéfinit l'admin pour les utilisateurs pour éviter l'édition de
champs
inutiles. On hérite de auth_admin.UserAdmin qui définit les urls d'accès
aux formulaire de changement de mot de passe, etc.
"""
ordering = ('username',)
list_display = ('username', 'first_name', 'last_name', 'is_active')
list_display_links = ('username',)
list_filter = ('is_active',)
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {'fields': ('is_active', 'is_superuser')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
(_('Groups'), {'fields': ('groups',)}),
)
readonly_fields = ('last_login', 'date_joined')
def save_model(self, request, obj, form, change):
"""
Redéfinition de save_model pour forcer tous les utilisateurs à faire
partie du staff (pour accéder à la partie admin) et superutilisateur
(pour pouvoir tout modifier) puisqu'on n'utilise pas de droit.
"""
# on force aussi le username en minuscules pour éviter les ambiguités
obj.username = obj.username.lower()
obj.is_superuser = False
obj.is_staff = True
obj.save()
class InlineStructure(admin.TabularInline):
model = contacts_models.Structure
extra = 0
readonly_fields = ('ville', 'type_pm', 'f_juridique', 'statut')
fields = readonly_fields
can_delete = False
can_add = False
verbose_name = "Personne Morale liée"
verbose_name_plural = "Personnes Morales liées"
fk_name = 'adherent'
def struct_detail(self, obj):
if obj.id is None:
return "-"
return format_html(
'<a href="{0}">{1}</a>', mark_safe(obj.get_absolute_url()), obj
)
struct_detail.short_description = "Désignation"
class AdminAdh(auth_admin.UserAdmin):
"""
On redéfinit l'admin pour les utilisateurs pour éviter l'édition de
champs
inutiles. On hérite de auth_admin.UserAdmin qui définit les urls d'accès
aux formulaire de changement de mot de passe, etc.
"""
ordering = ('username',)
list_display = ('username', 'is_active')
list_display_links = ('username',)
list_filter = ('is_active',)
fieldsets = (
(None, {'fields': ('username', 'is_active', 'password')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
readonly_fields = ('last_login', 'date_joined')
inlines = (InlineStructure,)
def save_model(self, request, obj, form, change):
"""
Redéfinition de save_model pour forcer tous les utilisateurs à faire
partie du staff (pour accéder à la partie admin)
"""
# on force aussi le username en minuscules pour éviter les ambiguités
obj.username = obj.username.lower()
obj.is_superuser = False
obj.is_staff = True
obj.save()
# ## Inline
# InlinePersonne doit être définie avant BaseAdminStructure
class InlinePersonne(admin.StackedInline):
"""
Classe de personnalisation de l'admin pour le modèle Personne en inline.
Note: on ne peut pas hériter de MixinAdminFiltrable à ce niveau à cause
car le fonctionnement n'est pas le même.
"""
form = admin_forms.PersonneAdminForm
model = contacts_models.Personne
readonly_fields = (
'date_creation',
'date_derniere_modification',
'utilisateur_derniere_modification',
)
fieldsets = (
(
'Désignation',
{
'fields': (
('civilite', 'nom', 'prenom', 'fonction'),
'structure',
('date_naissance', 'date_installation'),
'reseaux_engagements',
),
'classes': ('collapse',),
},
),
(
'Coordonnées',
{
'fields': (
'adresse',
'commune',
('code_postal', 'ville'),
'courrier_structure',
'tel_fixe',
'tel_mobile',
'fax',
'courriel',
'pas_de_courriel',
),
'classes': ('collapse',),
},
),
(
'Enregistrement',
{
'fields': (
(
'date_creation',
'date_derniere_modification',
'utilisateur_derniere_modification',
),
),
'classes': ('collapse',),
},
),
)
extra = 0
class InlinePersonneRo(InlinePersonne):
readonly_fields = get_readonly_field(InlinePersonne)
can_delete = False
can_add = False
class FieldsProjetBio(object):
radio_fields = {
"pond_savoirfaire": admin.HORIZONTAL,
"pond_motivation": admin.HORIZONTAL,
"pond_entourage": admin.HORIZONTAL,
"pond_foncier": admin.HORIZONTAL,
"pond_materiel": admin.HORIZONTAL,
"pond_reglementation": admin.HORIZONTAL,
"pond_commercialisation": admin.HORIZONTAL,
"pond_financement": admin.HORIZONTAL,
"pond_maindoeuvre": admin.HORIZONTAL,
}
@classmethod
def get_fieldsets(cls, collapse=False):
return (
(
'Projet',
{
'fields': (
'agriculteur',
'technicien',
'description',
'freins_identifies',
'pond_savoirfaire',
'pond_motivation',
'pond_entourage',
'pond_foncier',
'pond_materiel',
'pond_reglementation',
'pond_commercialisation',
'pond_financement',
'pond_maindoeuvre',
'suites_a_donner',
'remarques',
('date_probable_certification', 'date_certification'),
('engagement_surf', 'engagement_oc_enjeu_eau'),
('installation_bio', 'date_engagement_oc'),
),
'classes': ('collapse', 'wide') if collapse else ('wide',),
},
),
)
class InlineProjetBio(admin.StackedInline):
"""
Inline pour affichage des projets bio dans le formulaire d'un Agriculteur.
"""
model = contacts_models.ProjetBio
extra = 0
radio_fields = FieldsProjetBio.radio_fields
fieldsets = FieldsProjetBio.get_fieldsets(collapse=True)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
"""
On exclut l'utilisateur « admin » de la liste des techniciens.
"""
if db_field.name == "technicien":
kwargs["queryset"] = auth_models.User.objects.exclude(
username='admin'
)
return super(InlineProjetBio, self).formfield_for_foreignkey(
db_field, request, **kwargs
)
class InlineProjetBioRo(InlineProjetBio):
readonly_fields = get_readonly_field(InlineProjetBio)
can_delete = False
can_add = False
class InlineAdhesionGabnorFormSet(BaseInlineFormSet):
"limiter l'affichage des adhesions aux 5 dernieres"
def get_queryset(self):
return super(InlineAdhesionGabnorFormSet, self).get_queryset()[:5]
class InlineAdhesionGabnor(admin.TabularInline):
""
model = contacts_models.AdhesionGabnor
verbose_name = "adhésion GAB"
verbose_name_plural = "adhésions GAB"
extra = 0
formset = InlineAdhesionGabnorFormSet
fieldsets = ((None, {'fields': (('date', 'montant', 'mode_reg'),)}),)
class InlineAdhesionGabnorRo(InlineAdhesionGabnor):
readonly_fields = get_readonly_field(InlineAdhesionGabnor)
can_delete = False
can_add = False
class InlineRdv(admin.TabularInline):
model = contacts_models.Rdv
extra = 0
form = admin_forms.RdvForm
verbose_name = "Rendez vous"
verbose_name_plural = "Rendez vous"
fields = (
'date',
'technicien',
'type_rdv',
'projet_bio',
'titre_evt',
'lieu',
'finance_prog',
'est_confirme',
)
autocomplete_fields = ('lieu',)
def get_formsets_with_inlines(self, *args, **kwargs):
return super(InlineRdv, self).get_formsets_with_inlines(
*args, **kwargs
)
class InlineRdvRo(InlineRdv):
readonly_fields = get_readonly_field(InlineRdv)
can_delete = False
can_add = False
class InlineRdvPersonne(admin.TabularInline):
model = contacts_models.RdvPersonne
extra = 0
verbose_name = "Participation personne"
verbose_name_plural = "Participations des personnes"
readonly_fields = ['is_organisateur']
fields = ('rdv', 'personne', 'is_organisateur')
autocomplete_fields = ('personne',)
class InlineRdvPersonneRo(InlineRdvPersonne):
readonly_fields = get_readonly_field(InlineRdvPersonne)
can_delete = False
can_add = False
class InlineRdvPersonneMorale(admin.StackedInline):
model = contacts_models.RdvPersonneMorale
extra = 0
verbose_name = "Participation personne morale "
verbose_name_plural = "Participations des personnes morales"
fields = ('rdv', 'rdv_detail', 'structure')
readonly_fields = ('rdv_detail',)
# Ce champs doit etre defini dans la classe qui herite _directement_
# de Stacked/Tabular Inline a cause d'une sombre histoire de metaclass
def rdv_detail(self, obj):
if obj.id is None or obj.rdv.id is None:
return "-"
return format_html(
'<a href="{0}">{1}</a>',
mark_safe(obj.rdv.get_absolute_url()),
obj.rdv,
)
rdv_detail.short_description = "Détail rdv"
class InlineRdvPersonneMoraleRo(InlineRdvPersonneMorale):
readonly_fields = get_readonly_field(InlineRdvPersonneMorale)
can_delete = False
can_add = False
class InlineRdvPersonneMoraleStruct(InlineRdvPersonneMorale):
verbose_name = "Participation aux rdv collectifs"
verbose_name_plural = "Participations aux rdv collectifs"
can_add = False
fields = ('rdv_detail', 'structure')
class InlineRdvPersonneMoraleStructRo(InlineRdvPersonneMoraleStruct):
readonly_fields = get_readonly_field(InlineRdvPersonneMorale)
can_delete = False
can_add = False
class InlineAssolement(admin.TabularInline):
"""
Classe d'admin pour les données d'assolement de l'observatoire.
"""
model = contacts_models.Assolement
form = admin_forms.FormAssolement
verbose_name = "Assolement"
verbose_name_plural = "Assolements"
extra = 0
fieldsets = (
(
None,
{
'fields': (
('culture', 'detail_culture'),
(
'surface_bio',
'surface_c1',
'surface_c2',
'surface_c3',
'surface_conv',
),
('tonnage', 'prix', 'client', 'type_circuit'),
)
},
),
)
formfield_overrides = {
db.models.DecimalField: {'widget': forms.TextInput(attrs={'size': 5})},
db.models.FloatField: {'widget': forms.TextInput(attrs={'size': 5})},
}
class InlineAssolementRo(InlineAssolement):
readonly_fields = get_readonly_field(InlineAssolement)
form = admin_forms.FormAssolementRo
can_delete = False
can_add = False
class InlineCommercialisation(admin.TabularInline):
"""
Classe d'admin pour les données de commercialisation de l'observatoire.
"""
model = contacts_models.Commercialisation
verbose_name = "Commercialisation"
verbose_name_plural = "Commercialisations"
extra = 0
fieldsets = (
(
None,
{
'fields': (
'type_produit',
'type_circuit',
'ch_aff',
'detail',
'bio',
)
},
),
)
formfield_overrides = {
db.models.TextField: {'widget': forms.Textarea(attrs={'rows': 2})}
}
class InlineCommercialisationRo(InlineCommercialisation):
readonly_fields = get_readonly_field(InlineCommercialisation)
can_delete = False
can_add = False
class InlineTransformation(admin.TabularInline):
"""
Classe d'admin pour les données de transformation de l'observatoire.
"""
model = contacts_models.Transformation
verbose_name = "Transformation"
verbose_name_plural = "Transformations"
extra = 0
formfield_overrides = {
db.models.TextField: {'widget': forms.Textarea(attrs={'rows': 2})}
}
fieldsets = (
(
None,
{
'fields': (
('ferme', 'type_pduit'),
'agrmt',
'list_pduit',
('part_vol_glob', 'est_bio'),
'lait_abattoirs_vl',
)
},
),
)
class InlineTransformationRo(InlineTransformation):
readonly_fields = get_readonly_field(InlineTransformation)
can_delete = False
can_add = False
class InlineDocumentJoint(admin.TabularInline):
fields = ('date_depot', 'document')
readonly_fields = ('date_depot',)
model = contacts_models.DocumentJoint
extra = 0
class InlineDocumentJointRo(InlineDocumentJoint):
def doc_detail(self, obj):
if obj.id is None or obj.rdv.id is None:
return "-"
return format_html(
'<a href="{0}">{1}</a>',
mark_safe(obj.document.url),
obj.document.name,
)
doc_detail.short_description = "Document"
fields = ('date_depot', 'doc_detail')
readonly_fields = fields
can_delete = False
can_add = False
# ## ModelAdmin
# Admin de Personne
class AdminPersonne(
PostSaveMsgMixin, basket.MixinBasketAdmin, admin.ModelAdmin
):
"""
Classe de personnalisation de l'admin pour le modèle Personne.
"""
list_display = ('nom', 'prenom', 'structure')
list_display_links = ('nom', 'prenom', 'structure')
list_filter = ('structure__type_pm', 'structure__statut')
actions = (
admv.gen_mailto,
admv.gen_csv_publipostage,
admv.gen_csv_complet,
)
basket_actions = actions
search_fields = ('nom', 'prenom')
def save_model(self, request, obj, form, change):
"automatically assign user's name who modify form"
obj.utilisateur_derniere_modification = request.user
obj.save()
inlines = (InlineRdvPersonne,)
class AdminPersonneRo(AdminPersonne):
def get_readonly_fields(self, request, obj):
return get_readonly_field(AdminPersonne)
inlines = (InlineRdvPersonneRo,)
def change_view(self, request, object_id, extra_context=None):
"ensure no data is saved on a readonly ModelAdmin"
request.method = 'GET' # never consider a POST
return super(AdminPersonneRo, self).change_view(
request, object_id, extra_context
)
class AdminStructure(
PostSaveMsgMixin,
basket.MixinBigFilter,
basket.MixinBasketAdmin,
admin.ModelAdmin,
):
"Classe de personnalisation de l'admin pour le modèle Structure."
class Media:
css = {"all": ("css/contacts.css",)}
js = ['js/list_filter_collapse.js']
# django.jQuery(
# "div#rdvpersonnemorale_set-group > div[id!='rdvpersonnemorale_set-empty']"
# ).toggle()
# change_list
list_display = (
'id',
'nom_affichage',
'statut',
'f_juridique',
'commune',
'type',
'get_date_premiere_conversion',
)
list_display_links = ('nom_affichage',)
search_fields = ('designation', 'personne__nom', 'commune__nom')
autocomplete_fields = ('commune',)
list_filter = (
'type_pm',
'statut',
'f_juridique',
'type_activite',
'type_activite_pri',
'commune__territoire',
'commune__petite_region',
'commune__arrondissement',
)
actions = (
admv.gen_mailto,
admv.gen_mailto_sympa,
admv.gen_csv_publipostage_pphy,
admv.gen_csv_publipostage_wo_pphy,
admv.gen_csv_complet,
)
basket_actions = actions
form = admin_forms.AgriculteurAdminForm
radio_fields = {"visibilite": admin.HORIZONTAL}
date_hierarchie = 'date_creation'
filter_horizontal = ('etiquettes', 'qual_compl', 'qual_compl_conv')
readonly_fields = (
'date_creation',
'date_derniere_modification',
'utilisateur_derniere_modification',
'premiere_adhesion',
'renouvellement_adhesion',
'adherent_edit',
'ass_total',
'ass_total_bio',
)
fieldsets = (
(
'Désignation',
{
'fields': (
('designation', 'type_pm'),
('adherent', 'adherent_edit'),
('siret', 'f_juridique', 'statut'),
'commentaire',
'visibilite',
'etiquettes',
)
},
),
(
'Coordonnées',
{
'fields': (
('adresse', 'non_courrier'),
'commune',
('code_postal', 'ville'),
'tel_fixe',
'tel_mobile',
'fax',
'courriel',
'site_web',
),
'classes': ('collapse',),
},
),
(
"Informations sur l'exploitation",
{
'fields': (
('type_activite', 'type_activite_pri'),
'qual_compl',
'qual_compl_conv',
('sau_eau', 'sau_eau_bio'),
('ass_total', 'ass_total_bio'),
),
'classes': ('collapse',),
},
),
(
'Infos adhésions Gabnor',
{
'fields': (('premiere_adhesion', 'renouvellement_adhesion'),),
'classes': ('collapse',),
},
),
(
'Contact',
{
'fields': (
'origine_contact',
('annee_contact', 'mois_contact'),
(
'date_creation',
'date_derniere_modification',
'utilisateur_derniere_modification',
),
),
'classes': ('collapse',),
},
),
)
inlines = (InlineAdhesionGabnor, InlinePersonne, InlineProjetBio)
classe_form_filtre = contacts_forms.FormFiltreStructure
class_form_big_filter = contacts_forms.FormFiltreStructure
def adherent_edit(self, obj):
if obj.id is None or obj.adherent is None:
return "-"
return format_html(
'<a href="{0}">{1}</a>',
mark_safe(
reverse(
"admin:contacts_adhlogin_change", args=[obj.adherent.id]
)
),
obj.adherent,
)
adherent_edit.short_description = "Détail compte adhérent"
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request):
resp = inline.get_formset(request, obj)
if resp.model == contacts_models.Rdv:
pass
yield resp
def nom_affichage(self, obj):
return str(obj)
nom_affichage.short_description = "Structure ou personne"
def save_model(self, request, obj, form, change):
"""
Redéfinition de save_model pour assigner automatiquement le nom de
l'utilisateur ayant effectué la modification.
"""
obj.utilisateur_derniere_modification = request.user
obj.save()
def save_formset(self, request, form, formset, change):
"update user who made last modification for inlines"
instances = formset.save(commit=False)
for instance in instances:
instance.utilisateur_derniere_modification = request.user
instance.save()
formset.save_m2m()
class AdminStructureRo(AdminStructure):
def get_readonly_fields(self, request, obj):
return get_readonly_field(AdminStructure)
inlines = (InlineAdhesionGabnorRo, InlinePersonneRo, InlineProjetBioRo)
def change_view(self, request, object_id, extra_context=None):
"ensure no data is saved on a readonly ModelAdmin"
request.method = 'GET' # never consider a POST
return super(AdminStructureRo, self).change_view(
request, object_id, extra_context
)
# ## Admin de ProjetBio et dépendances
class AdminProjetBio(
PostSaveMsgMixin, basket.MixinBasketAdmin, admin.ModelAdmin
):
"""
Classe d'admin pour afficher les projets bio de façon indépendante.
"""
list_display = ('__str__', 'agri_id')
list_display_links = ('__str__',)
inlines = (InlineRdv,)
search_fields = (
'agriculteur__designation',
'agriculteur__personne__nom',
'agriculteur__commune__nom',
)
list_filter = (TechnicienFilter,)
actions = (admv.gen_csv_complet,)
basket_actions = (admv.gen_csv_complet,)
radio_fields = FieldsProjetBio.radio_fields
fieldsets = FieldsProjetBio.get_fieldsets(collapse=False)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "technicien":
kwargs["queryset"] = auth_models.User.objects.exclude(
username='admin'
)
return super(AdminProjetBio, self).formfield_for_foreignkey(
db_field, request, **kwargs
)
class AdminProjetBioRo(AdminProjetBio):
def get_readonly_fields(self, request, obj):
return get_readonly_field(AdminProjetBio)
inlines = (InlineRdvRo,)
def change_view(self, request, object_id, extra_context=None):
"ensure no data is saved on a readonly ModelAdmin"
request.method = 'GET' # never consider a POST
return super(AdminProjetBioRo, self).change_view(
request, object_id, extra_context
)
class AdminDonneesBio(
PostSaveMsgMixin, basket.MixinBasketAdmin, admin.ModelAdmin
):
"""
Classe d'admin pour les données de l'observatoire (également éditées
dans les formulaires des agriculteurs bio).
"""
inlines = (InlineAssolement, InlineCommercialisation, InlineTransformation)
search_fields = (
'agriculteur_bio__designation',
'agriculteur_bio__personne__nom',
'agriculteur_bio__commune__nom',
)
list_filter = ('annee',)
list_display = ('__str__', 'agri_id')
# date_hierarchy = 'date_collecte'
actions = (
admv.gen_csv_complet,
admv.gen_csv_assolement,
admv.gen_csv_commercialisation,
admv.gen_csv_transformation,
)
basket_actions = (admv.gen_csv_complet,)
# Ne fonctionne pas correctement -> à voir
formfield_overrides = {
db.models.BooleanField: {'widget': forms.CheckboxInput}
}
readonly_fields = (
'ass_total',
'ass_total_bio',
'com_ca_total',
'com_pct_ca_bio',
'agri_detail',
)
fieldsets = (
(
None,
{
'fields': (
('agriculteur_bio', 'agri_detail'),
('date_collecte', 'technicien'),
'annee',
'organisme_certification',
'biodynamie',
'remarques',
)
},
),
(
"Aides",
{
'fields': (
('aide_conversion_ab', 'date_aide_conversion_ab'),
(
'aide_maintien_ab',
'aide_credit_impot',
'aide_certification_bio',
),
('aide_investissement', 'aide_installation', 'aide_mae_t'),
'aide_autres',
('aide_accompagnement', 'aide_accompagnement_precisions'),
),
'classes': ('wide', 'collapse'),
},
),
(
"Main d'œuvre",
{
'fields': (
('etp_associes', 'etp_familiaux'),
('etp_salaries_permanents', 'etp_saisonniers'),
('etp_encadrants', 'personnes_insertion'),
),
'classes': ('wide', 'collapse'),
},
),
(
"Transmission",
{
'fields': (
('tr_date_fin_prevue', 'tr_repreneur_ident'),
'tr_precisions',
),
'classes': ('wide', 'collapse'),
},
),
(
"Commercialisation",
{
'fields': (
('statut_commercialisation', 'statut_choisi'),
('com_ca_total', 'com_pct_ca_bio'),
),
'classes': ('wide', 'collapse'),
},
),
(
'Accueil',
{
'fields': (
('acc_act_tour', 'acc_act_peda'),
('acc_rest_bio', 'acc_act_autre'),
'detail_activites',
),
'classes': ('wide', 'collapse'),
},
),
(
"Lait de vaches",
{
'fields': (
# lait
('lait_vaches', 'lait_nb_vaches'),
('lait_quota_laiterie', 'lait_quota_vente_directe'),
('lait_prod_laiterie', 'lait_prod_vente_directe'),
'lait_laiterie',
# viande issue de vaches laitières
),
'classes': ('wide', 'collapse'),
},
),
(
"Lait de chèvres",
{
'fields': (
(
'lait_chevres',
'lait_nb_chevres',
'lait_chevres_conversion',
),
'lait_chevres_prod',
),
'classes': ('wide', 'collapse'),
},
),
(
"Viande bovine",
{
'fields': (
('bovine', 'bovine_nb_va'),
('bovine_reformes_cl', 'bovine_taurillons_cl'),
('bovine_adultes_cc', 'bovine_veaux_cc'),
('lait_reformes_cl', 'lait_taurillons_cl'),
('lait_adultes_cc', 'lait_veaux_cc'),
),
'classes': ('wide', 'collapse'),
},
),
(
"Porcs",
{
'fields': (('porcs', 'porcs_nb_truies'), 'porcs_nb_com'),
'classes': ('wide', 'collapse'),
},
),
(
"Moutons",
{
'fields': (
('moutons', 'moutons_nb_brebis'),
'moutons_nb_agn_com',
),
'classes': ('wide', 'collapse'),
},
),
(
"Petits animaux",
{
'fields': (
('animaux_lapins', 'animaux_volailles'),
'animaux_volailles_chair',
'animaux_nb_poulets',
'animaux_nb_lapins',
'animaux_nb_autres_volailles',
),
'classes': ('wide', 'collapse'),
},
),
(
"Autres productions animales",
{
'fields': (
'animaux_autres_prod',
'animaux_details_autres_prod',
),
'classes': ('wide', 'collapse'),
},
),
(
"Œufs",
{
'fields': (
'oeufs_production_bio',
'oeufs_nb_pondeuses',
'oeufs_nb_oeufs',
'oeufs_acheteur_cl',
),
'classes': ('wide', 'collapse'),
},
),
(
"Miel",
{
'fields': ('miel_production_bio', 'miel_nb_ruches'),
'classes': ('wide', 'collapse'),
},
),
(
"Formation",
{
'fields': (
('formation_annee', 'formation_annee_laquelle'),
'formation_annee_commentaire',
('formation_avenir', 'formation_avenir_type'),
'formation_avenir_details',
),
'classes': ('wide', 'collapse'),
},
),
(
"Surface d'assolement",
{
'fields': (('ass_total', 'ass_total_bio'),),
'classes': ('wide',),
},
),
)
class AdminDonneesBioRo(AdminDonneesBio):
def get_readonly_fields(self, request, obj):
return get_readonly_field(AdminDonneesBio)
inlines = (
InlineAssolementRo,
InlineCommercialisationRo,
InlineTransformationRo,
)
def change_view(self, request, object_id, extra_context=None):
"ensure no data is saved on a readonly ModelAdmin"
request.method = 'GET' # never consider a POST
return super(AdminDonneesBioRo, self).change_view(
request, object_id, extra_context
)
# ## Admin de AdhesionGabnor
class AdminAdhesionGabnor(basket.MixinBasketAdmin, admin.ModelAdmin):
"""
Classe d'admin pour les adhésions Gabnor (également éditées
dans les formulaires des agriculteurs bio).
"""
date_hierarchy = 'date'
list_filter = ('date', 'mode_reg')
search_fields = (
'agriculteur_bio__designation',
'agriculteur_bio__personne__nom',
'agriculteur_bio__commune__nom',
)
actions = (admv.gen_csv_complet,)
basket_actions = (admv.gen_csv_complet,)
fields = ('agriculteur_bio', 'date', 'montant', 'mode_reg', 'annee')
class AdminAdhesionGabnorRo(AdminAdhesionGabnor):
def get_readonly_fields(self, request, obj):
return get_readonly_field(AdminAdhesionGabnor)
def change_view(self, request, object_id, extra_context=None):
"ensure no data is saved on a readonly ModelAdmin"
request.method = 'GET' # never consider a POST
return super(AdminAdhesionGabnorRo, self).change_view(
request, object_id, extra_context
)
class AdminRdv(
PostSaveMsgMixin,
basket.MixinBasketAdmin,
LookupAllowedMixin,
admin.ModelAdmin,
):
search_fields = (
'titre_evt__designation',
'lieu__nom',
'personne_morale__designation',
'personne_morale__personne__nom',
'rdvpersonnemorale__structure__designation',
'rdvpersonnemorale__structure__personne__nom',
)
nop_autocomplete_fields = (
'personne_morale',
'lieu',
'organisateur',
'intervenant',
)
lookup_allowed_tags = (
'projet_bio__technicien__id__exact',
'personnes__structure',
)
list_filter = ('type_rdv', ProjetBioTechnicienFilter, TechnicienFilter)
list_display = (
'date',
'type_rdv',
'technicien',
'personne_morale',
'titre_evt',
)
date_hierarchy = 'date'
basket_actions = (
admv.gen_csv_rdv_ind,
admv.gen_csv_rdv_coll,
admv.gen_csv_rdv_coll_det,
)
actions = (
admv.gen_csv_rdv_ind,
admv.gen_csv_rdv_coll,
admv.gen_csv_rdv_coll_det,
)
readonly_fields = ('struct_af_org', 'struct_af_int')
fieldsets = (
(
None,
{
'fields': (
('date', 'type_rdv'),
('technicien', 'lieu'),
'commentaire',
('finance_prog', 'acc_duree', 'acc_distance'),
)
},
),
(
"Rendez vous individuels",
{'fields': (('personne_morale', 'projet_bio'),)},
),
(
"Évenements collectifs",
{
'fields': (
('est_confirme', 'titre_evt'),
('territoire_cible', 'public_cible'),
('organisateur', 'struct_af_org'),
('intervenant', 'struct_af_int'),
('objectif', 'res_attendu'),
)
},
),
)
form = admin_forms.RdvForm
inlines = (InlineRdvPersonne, InlineDocumentJoint)
class AdminRdvRo(AdminRdv):
def get_readonly_fields(self, request, obj):
return get_readonly_field(AdminRdv)
inlines = (InlineRdvPersonneRo, InlineDocumentJointRo)
def change_view(self, request, object_id, extra_context=None):
"ensure no data is saved on a readonly ModelAdmin"
request.method = 'GET' # never consider a POST
return super(AdminRdvRo, self).change_view(
request, object_id, extra_context
)
# ## Enregistrement des modèles à administrer
def register_models(site):
"""
Enregistrement des modèles dans un AdminSite passé en paramètre.
"""
# Modèle User avec admin personnalisée
site.register(auth_models.User, AdminUser)
site.register(auth_models.Group, auth_admin.GroupAdmin)
# Modèles principaux indispensables
site.register(contacts_models.Structure, AdminStructure)
site.register(contacts_models.StructureRo, AdminStructureRo)
site.register(contacts_models.Personne, AdminPersonne)
site.register(contacts_models.PersonneRo, AdminPersonneRo)
# Facultatif: administration indépendante de données qu'on retrouve dans en
# inline dans les autres pages.
site.register(contacts_models.ProjetBio, AdminProjetBio)
site.register(contacts_models.ProjetBioRo, AdminProjetBioRo)
site.register(contacts_models.DonneesBio, AdminDonneesBio)
site.register(contacts_models.DonneesBioRo, AdminDonneesBioRo)
site.register(contacts_models.AdhesionGabnor, AdminAdhesionGabnor)
site.register(contacts_models.AdhesionGabnorRo, AdminAdhesionGabnorRo)
site.register(contacts_models.Rdv, AdminRdv)
site.register(contacts_models.RdvRo, AdminRdvRo)
site.register(contacts_models.DocumentJoint)
site.register(contacts_models.AdhLogin, AdminAdh)
# fait dans urls.py
# register_models(site)
# EOF
Map all the world