Skip to content
This repository has been archived by the owner on Mar 3, 2025. It is now read-only.

Commit

Permalink
Merge pull request #32 from FaouziaTek/version-1.2.8.3
Browse files Browse the repository at this point in the history
Version 1.2.8.3
  • Loading branch information
FaouziaTek authored Feb 3, 2025
2 parents bfca6f7 + ae88e31 commit e236e4f
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 240 deletions.
2 changes: 1 addition & 1 deletion noethysweb/consommations/utils/utils_impression_conso.py
Original file line number Diff line number Diff line change
Expand Up @@ -1355,7 +1355,7 @@ def Exporter_excel(self, dict_donnees=None):

def Get_questions_evenement(self, conso=None):
liste_questions_str = []
if conso["evenement"].categorie.questions and conso["extra"]:
if conso["evenement"].categorie and conso["evenement"].categorie.questions and conso["extra"]:
reponses = json.loads(conso["extra"])
liste_idquestion = [int(idq) for idq in conso["evenement"].categorie.questions.split(";")]
for question in self.liste_questions:
Expand Down
18 changes: 18 additions & 0 deletions noethysweb/core/migrations/0184_devis_prestations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.21 on 2025-02-02 15:46

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0183_portailperiode_mode_consultation_date'),
]

operations = [
migrations.AddField(
model_name='devis',
name='prestations',
field=models.TextField(blank=True, null=True, verbose_name='Prestations'),
),
]
18 changes: 18 additions & 0 deletions noethysweb/core/migrations/0185_attestation_prestations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.21 on 2025-02-02 20:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('core', '0184_devis_prestations'),
]

operations = [
migrations.AddField(
model_name='attestation',
name='prestations',
field=models.TextField(blank=True, null=True, verbose_name='Prestations'),
),
]
2 changes: 2 additions & 0 deletions noethysweb/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2876,6 +2876,7 @@ class Attestation(models.Model):
total = models.DecimalField(verbose_name="Total", max_digits=10, decimal_places=2, default=0.0)
regle = models.DecimalField(verbose_name="Réglé", max_digits=10, decimal_places=2, default=0.0)
solde = models.DecimalField(verbose_name="Solde", max_digits=10, decimal_places=2, default=0.0)
prestations = models.TextField(verbose_name="Prestations", blank=True, null=True)

class Meta:
db_table = 'attestations'
Expand All @@ -2899,6 +2900,7 @@ class Devis(models.Model):
total = models.DecimalField(verbose_name="Total", max_digits=10, decimal_places=2, default=0.0)
regle = models.DecimalField(verbose_name="Réglé", max_digits=10, decimal_places=2, default=0.0)
solde = models.DecimalField(verbose_name="Solde", max_digits=10, decimal_places=2, default=0.0)
prestations = models.TextField(verbose_name="Prestations", blank=True, null=True)

class Meta:
db_table = 'devis'
Expand Down
55 changes: 27 additions & 28 deletions noethysweb/core/templates/core/widgets/checktree.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,39 +26,38 @@
{% endblock styles %}

{% if not liste_branches1 and texte_si_vide %}
<strong>{{ texte_si_vide }}</strong>
{% endif %}

<div id="div_table_{{ id }}">
<table id="table_{{ id }}" class="table table-bordered">
{% for dict_branche1 in liste_branches1 %}
<tr>
<td class="ligne_regroupement">
<div>
<input type="checkbox" class="check_branche1" data-idbranche1="{{ dict_branche1.pk }}">
<span style="margin-left: 2px;margin-right:20px;font-weight: bold;">{{ dict_branche1.label }}</span>
</div>
</td>
</tr>
{% for dict_branche2 in dict_branches2|get_item:dict_branche1.pk %}
<div style="border: solid 1px #ced4da; padding: 5px;">{{ texte_si_vide }}</div>
{% else %}
<div id="div_table_{{ id }}">
<table id="table_{{ id }}" class="table table-bordered mb-0">
{% for dict_branche1 in liste_branches1 %}
<tr>
<td>
<div style="padding-left:20px;">
{% if dict_branche2.checkable != False %}
<input name="{{ name }}" type="checkbox" class="check_branche2" data-idbranche1="{{ dict_branche1.pk }}" value="{{ dict_branche2.pk }}" {% if dict_branche2.pk in selections or coche_tout %}checked{% endif %}>
{% if dict_branche2.pk in selections or coche_tout %}
<script>$("#div_table_{{ id }} .check_branche1[data-idbranche1='{{ dict_branche1.pk }}']").prop("checked", true);</script>
{% endif %}
{% endif %}
<span style="margin-left: 2px;margin-right:20px;">{{ dict_branche2.label }}</span>
<td class="ligne_regroupement">
<div>
<input type="checkbox" class="check_branche1" data-idbranche1="{{ dict_branche1.pk }}">
<span style="margin-left: 2px;margin-right:20px;font-weight: bold;">{{ dict_branche1.label }}</span>
</div>
</td>
</tr>
{% for dict_branche2 in dict_branches2|get_item:dict_branche1.pk %}
<tr>
<td>
<div style="padding-left:20px;">
{% if dict_branche2.checkable != False %}
<input name="{{ name }}" type="checkbox" class="check_branche2" data-idbranche1="{{ dict_branche1.pk }}" value="{{ dict_branche2.pk }}" {% if dict_branche2.pk in selections or coche_tout %}checked{% endif %}>
{% if dict_branche2.pk in selections or coche_tout %}
<script>$("#div_table_{{ id }} .check_branche1[data-idbranche1='{{ dict_branche1.pk }}']").prop("checked", true);</script>
{% endif %}
{% endif %}
<span style="margin-left: 2px;margin-right:20px;">{{ dict_branche2.label }}</span>
</div>
</td>
</tr>
{% endfor %}
{% endfor %}
{% endfor %}
</table>
</div>

</table>
</div>
{% endif %}

<script>

Expand Down
2 changes: 1 addition & 1 deletion noethysweb/core/utils/utils_infos_individus.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def GetDictIndividus(self):
"INDIVIDU_RUE": individu.rue_resid,
"INDIVIDU_CP": individu.cp_resid,
"INDIVIDU_VILLE": individu.ville_resid,
"INDIVIDU_SECTEUR": individu.secteur,
"INDIVIDU_SECTEUR": individu.secteur.nom if individu.secteur else "",
"INDIVIDU_SECTEUR_COLORE": ("<font color='%s'>%s</font>" % (individu.secteur.couleur or "#000000", individu.secteur)) if individu.secteur else "",
"INDIVIDU_CATEGORIE_TRAVAIL": individu.categorie_travail,
"INDIVIDU_PROFESSION": individu.profession,
Expand Down
5 changes: 4 additions & 1 deletion noethysweb/facturation/utils/utils_facturation.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def GetListeTriee(self, dict_factures={}):
def GetDonnees(self, liste_factures=[], liste_activites=[], date_debut=None, date_fin=None, date_edition=None,
date_echeance=None, categories_prestations=["consommation", "cotisation", "location", "autre"],
type_label="0", date_anterieure=None, mode="facture", IDfamille=None, liste_IDindividus=[], filtre_prestations=None, exclusions_prestations=None,
impayes_factures=False, inclure_cotisations_si_conso=False):
impayes_factures=False, inclure_cotisations_si_conso=False, liste_conditions=None):
""" Recherche des factures à créer """
logger.debug("Recherche les données de facturation...")

Expand Down Expand Up @@ -97,6 +97,9 @@ def GetDonnees(self, liste_factures=[], liste_activites=[], date_debut=None, dat
if exclusions_prestations:
for nom_prestation in exclusions_prestations.split(";"):
conditions &= ~Q(label__icontains=nom_prestation.strip())
# Liste de conditions
if liste_conditions:
conditions &= liste_conditions

logger.debug("Recherche des prestations des factures...")
prestations = Prestation.objects.select_related('famille', 'activite', 'individu', 'tarif', 'categorie_tarif', "tarif__nom_tarif").filter(conditions).order_by("date")
Expand Down
114 changes: 41 additions & 73 deletions noethysweb/fiche_famille/forms/famille_attestations.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,36 @@
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Hidden, HTML
from crispy_forms.bootstrap import Field
from core.forms.select2 import Select2Widget, Select2MultipleWidget
from core.forms.select2 import Select2Widget
from core.forms.base import FormulaireBase
from core.utils.utils_commandes import Commandes
from core.models import Attestation, ModeleDocument, Inscription
from core.models import Attestation, ModeleDocument
from core.widgets import DatePickerWidget, DateRangePickerWidget, FormIntegreWidget
from core.utils import utils_dates
from facturation.forms.attestations_options_impression import Formulaire as Form_options_impression
from fiche_famille.widgets import Prestations_devis


class Formulaire(FormulaireBase, ModelForm):
periode = forms.CharField(label="Période", required=True, widget=DateRangePickerWidget())
date_edition = forms.DateField(label="Date d'édition", required=True, widget=DatePickerWidget(attrs={'afficher_fleches': True}), help_text="Par défaut la date du jour. Modifiez uniquement si nécessaire.")
individus = forms.MultipleChoiceField(label="Individus", widget=Select2MultipleWidget(), choices=[], required=True)
activites = forms.MultipleChoiceField(label="Activités", widget=Select2MultipleWidget(), choices=[], required=True)
numero = forms.IntegerField(label="Numéro", required=True, help_text="Ce numéro est attribué par défaut. Modifiez uniquement si nécessaire.")
modele = forms.ModelChoiceField(label="Modèle de document", widget=Select2Widget(), queryset=ModeleDocument.objects.filter(categorie="attestation").order_by("nom"), required=True)
periode = forms.CharField(label="Période", required=True, widget=DateRangePickerWidget(), help_text="Sélectionnez la période à inclure dans l'attestation.")
date_edition = forms.DateField(label="Date d'édition", required=True, widget=DatePickerWidget(attrs={'afficher_fleches': True}), help_text="La date d'édition est par défaut la date du jour. Il est généralement inutile de la modifier.")
numero = forms.IntegerField(label="Numéro", required=True, help_text="Le numéro de l'attestation est généré automatiquement. Il est généralement inutile de le modifier.")
modele = forms.ModelChoiceField(label="Modèle de document", widget=Select2Widget(), queryset=ModeleDocument.objects.filter(categorie="attestation").order_by("nom"), required=True, help_text="Sélectionnez le modèle de document à utiliser. Il doit avoir au préalable été créé dans Menu Paramétrage > Modèles de documents > Attestation.")
signataire = forms.CharField(label="Signataire", required=True, help_text="Saisissez le nom du signataire du document (par défaut l'utilisateur en cours).")
options_impression = forms.CharField(label="Options d'impression", required=False, widget=FormIntegreWidget())
prestations = forms.CharField(label="Prestations", required=False, widget=Prestations_devis(
attrs={"texte_si_vide": "Aucune prestation", "hauteur_libre": True, "coche_tout": False}), help_text="Cochez les types de prestations à inclure dans l'attestation.")

class Meta:
model = Attestation
fields = ["famille", "numero", "filtre_prestations", "exclusions_prestations"]
help_texts = {
"filtre_prestations": "Si vous souhaitez uniquement certaines prestations, tapez leur nom ou une partie de leur nom, séparées par des points-virgules (;). Exemple : journées avec repas;piscine;matin.",
"exclusions_prestations": "Si vous souhaitez exclure certaines prestations, tapez leur nom ou une partie de leur nom, séparées par des points-virgules (;). Exemple : journées avec repas;piscine;matin.",
}
fields = ["famille", "numero"]

def __init__(self, *args, **kwargs):
idfamille = kwargs.pop("idfamille")
utilisateur = kwargs.pop("utilisateur", None)
super(Formulaire, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'famille_attestations_form'
self.helper.form_id = 'famille_devis_form'
self.helper.form_method = 'post'

self.helper.form_class = 'form-horizontal'
Expand All @@ -51,19 +48,6 @@ def __init__(self, *args, **kwargs):
# Date d'édition
self.fields["date_edition"].initial = datetime.date.today()

# Recherche les inscriptions de la famille
inscriptions = Inscription.objects.select_related("activite", "activite__structure", "individu").filter(famille_id=idfamille, activite__structure__in=utilisateur.structures.all())

# Individus
liste_individus = list({(inscription.individu_id, inscription.individu.prenom): None for inscription in inscriptions}.keys())
self.fields["individus"].choices = liste_individus
self.fields["individus"].initial = [id for id, nom in liste_individus]

# Activités
liste_activites = list({(inscription.activite_id, inscription.activite.nom): None for inscription in inscriptions}.keys())
self.fields["activites"].choices = liste_activites
self.fields["activites"].initial = [id for id, nom in liste_activites]

# Numéro
self.fields["numero"].initial = 1
if not self.instance.idattestation:
Expand All @@ -84,9 +68,8 @@ def __init__(self, *args, **kwargs):
if self.instance.idattestation:
self.fields["numero"].initial = self.instance.numero
self.fields["date_edition"].initial = self.instance.date_edition
self.fields["individus"].initial = [int(idindividu) for idindividu in self.instance.individus.split(";")] if self.instance.individus else []
self.fields["activites"].initial = [int(idindividu) for idindividu in self.instance.activites.split(";")] if self.instance.activites else []
self.fields["periode"].initial = "%s - %s" % (utils_dates.ConvertDateToFR(self.instance.date_debut), utils_dates.ConvertDateToFR(self.instance.date_fin))
self.fields["prestations"].initial = self.instance.prestations

# Options : Ajoute le request au form
self.fields['options_impression'].widget.attrs.update({"form": Form_options_impression(request=self.request)})
Expand All @@ -98,22 +81,19 @@ def __init__(self, *args, **kwargs):
HTML("""<button class='btn btn-primary' onclick="impression_pdf(false, false)"><i class="fa fa-check margin-r-5"></i>Enregistrer</button> """)
],
autres_commandes=[
HTML("""<a type='button' class='btn btn-default' title="Envoyer par Email" onclick="impression_pdf(true, false)" href='#'><i class="fa fa-send-o margin-r-5"></i>Envoyer par email</a> """),
HTML("""<a type='button' class='btn btn-default' title="Aperçu PDF" href='#' onclick="impression_pdf(false, true)"><i class="fa fa-file-pdf-o margin-r-5"></i>Aperçu PDF</a> """),
HTML("""<a type='button' class='btn btn-default' title="Envoyer par Email" onclick="impression_pdf(true, false)" href='javascript:void(0)'><i class="fa fa-send-o margin-r-5"></i>Envoyer par email</a> """),
HTML("""<a type='button' class='btn btn-default' title="Aperçu PDF" href='javascript:void(0)' onclick="impression_pdf(false, true)"><i class="fa fa-file-pdf-o margin-r-5"></i>Aperçu PDF</a> """),
]),
Hidden('famille', value=idfamille),
Hidden('infos', value=""),
Hidden("prestations_defaut", value=self.fields["prestations"].initial or ""),
Field("periode"),
Field("prestations"),
Field("date_edition"),
Field("individus"),
Field("activites"),
Field("filtre_prestations"),
Field("exclusions_prestations"),
Field("numero"),
Field("modele"),
Field("signataire"),
Field("options_impression"),
HTML(EXTRA_HTML),
)

def clean(self):
Expand All @@ -131,40 +111,28 @@ def clean(self):
return self.cleaned_data


EXTRA_HTML = """
{# Insertion des modals #}
{% include 'outils/modal_editeur_emails.html' %}
{% include 'core/modal_pdf.html' %}
{% load static %}
<script>
// Impression du PDF
function impression_pdf(email=false, afficher=true) {
$.ajax({
type: "POST",
url: "{% url 'ajax_attestation_impression_pdf' %}",
data: $("#famille_attestations_form").serialize(),
datatype: "json",
success: function(data){
$('input[name=infos]').val(JSON.stringify(data.infos));
if (email) {
envoyer_email(data)
}
if (afficher) {
charge_pdf(data);
}
if ((email === false) & (afficher == false)) {
$("#famille_attestations_form").submit()
};
},
error: function(data) {
toastr.error(data.responseJSON.erreur);
}
})
};
</script>
"""
class Formulaire_prestations(FormulaireBase, forms.Form):
prestations = forms.CharField(label="Prestations", required=False, widget=Prestations_devis(
attrs={"texte_si_vide": "Aucune prestation", "hauteur_libre": True, "coche_tout": True}),
help_text="Cochez les types de prestations à inclure dans l'attestation.")

def __init__(self, *args, **kwargs):
prestations = kwargs.pop("prestations", {})
selections = kwargs.pop("selections", {})
super(Formulaire_prestations, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_id = 'famille_devis_prestations_form'
self.helper.form_method = 'post'

self.helper.form_class = 'form-horizontal'
self.helper.label_class = 'col-md-2'
self.helper.field_class = 'col-md-10'

self.fields["prestations"].widget.attrs.update({"prestations": prestations, "selections": selections})
if selections:
self.fields["prestations"].widget.attrs.update({"coche_tout": False})

# Affichage
self.helper.layout = Layout(
Field("prestations"),
)
Loading

0 comments on commit e236e4f

Please sign in to comment.