Résolue

Création d'une application de planning

# CRM

Bonjour,
Je souhaiterai créer une application de planning ou en back office on gere une liste d'employés individuellement et indiquer leur lieu de chantier et la période. (au jour ou a la semaine). J'ai du mal a visualiser par quoi commencer. Un peu comme un agenda familiale mais plus simple. Si vous pouvez m'aiguiller pour savoir ou regarder !
merci d'avance.
yann

Gabriel Trouvé

Mentor

Bonjour Yann,

Je te propose Django comme framework :).

Tu peux créer des employées dans ta base de données.
Ensuite, leur assigner un lieu, et une date de début et de fin de travaux.

Tu peux donc créer des modèles avec django, et utiliser une bibliothèque si tu veux pour l'agenda, ou pour commencer, rendre de manière basique les assignations des employées dans le template.

Qu'en penses-tu ? :)

Merci pour ton retour, oui c'est exactement ce que j'allais utilisé Django, gràce a Docstring je suis débutant++ sur Django. Mais quel bibliothèque je peux utilisé ? J'ai fouillé dans la doc de Django mais je dois encore trop novice pour decerné ce dons j'ai besoin. J'ai trouvé sur Git une personne a créer Event Calendar avec son mode d'utilisation etc mais j'aimerai reussir à parti de zero pour comprendre tout le code. Il me manque ce petit point de départ, affiché ce calendrier.

Merci d'avance pour ton aide.

Il te faut un peu d'entrainement avec django alors.
Mais en gros des idées pour les modèles :

from django.db import models

class Employe(models.Model):
    nom = models.CharField(max_length=100)
    prenom = models.CharField(max_length=100)

class Chantier(models.Model):
    nom = models.CharField(max_length=200)
    adresse = models.TextField()

class Affectation(models.Model):
    employe = models.ForeignKey(Employe, on_delete=models.CASCADE)
    chantier = models.ForeignKey(Chantier, on_delete=models.CASCADE)
    date_debut = models.DateField()
    date_fin = models.DateField()

Et tu pourrais utiliser cette lib en template :
https://fullcalendar.io/

Puis envoyer les informations via une vue.

Commence par bien penser tes modèles :).

Une fois les modèles en place, c'est plus simple pour la suite.

Merci Gabriel, je viens de finir de créer mon calendrier avec fullcalendar ( qui est juste top au passage comme librairie merci pour le tuyau ! ). J'en suis au passage de récupération de la base de données au planning coté visiteur. J'ai vu qu'on pouvait utiliser les fichiers JSON pour récupérés les données pour être visible sur le planning mais tu parle dans ton précédents message via une vue. Qu'entend tu par via une vue ? Je n'arrive pas à visualisé cela

Merci envore pour ton aide

Salut :)

En gros tu pourrais te faire une vue API, qui n'utilise pas de template. Mais elle renvoie des données au format json.

from django.http import JsonResponse
from .models import Affectation

def affectations_json(request):
    affectations = Affectation.objects.all()

    events = []
    for affectation in affectations:
        events.append({
            'title': f"{affectation.employe.prenom} {affectation.employe.nom} - {affectation.chantier.nom}",
            'start': affectation.date_debut.isoformat(),
            'end': affectation.date_fin.isoformat(),
        })

    return JsonResponse(events, safe=False)

Et ensuite, tu te fais ton url, ce qui pourrais te permettre de consommer les données de ta vue pour le calendrier.

Donc une vue avec ton template qui renvoie le calendrier, et une qui sera juste consommée dans le template. Donc pour les urls du genre :

from django.urls import path
from . import views

urlpatterns = [
    path('calendrier/', views.calendrier_view, name='calendrier'),
    path('affectations_json/', views.affectations_json, name='affectations_json'),
]

Bonne fin d'après-midi ! :)

Hello !

J'arrive a récupérer un URL avec mes informations au format JSON grace a tes explication ( TOP ) mais je n'arrive pas à les afficher sur mon planning. Et la malheureusement je crois que c'est coté JS ou je dois me planté.... je sais qu'on parle que de python mais voici mon code JS si quelqu'un voit l'erreur

window.onload = () => {
    let elementCalendrier = document.getElementById("calendrier")

    let xmlhttp = new XMLHttpRequest()

    xmlhttp.onreadystatechange = () => {
        if(xmlhttp.readyState) == 4) {
            if(xmlhttp.status == 200){
                let evenements = JSON.parse(xmlhttp.responseURL)

                    // on instancie le calendrier
                    let calendrier = new FullCalendar.Calendar(elementCalendrier, {
                        // on appelle les composants
                        plugins: ['dayGrid'],
                        locale: 'fr',
                        buttonText:{
                            today:'Aujourd\'hui'
                        },
                        events: evenements
                    })

                    calendrier.render()
            }
        }
    }

    xmlhttp.open('get','http://127.0.0.1:8000/affectations_json/', true )
    xmlhttp.send(null)

}

Merci d'avance !

Alors, tu pourrais essayer avec :

document.addEventListener('DOMContentLoaded', function() {
    let elementCalendrier = document.getElementById("calendrier");

    fetch('http://127.0.0.1:8000/affectations_json/')
        .then(response => response.json())
        .then(evenements => {
            let calendrier = new FullCalendar.Calendar(elementCalendrier, {
                plugins: ['dayGrid'],
                locale: 'fr',
                buttonText: {
                    today: 'Aujourd\'hui'
                },
                events: evenements
            });

            calendrier.render();
        })
        .catch(error => console.error('Erreur lors du chargement des événements:', error));
});

Plutôt quelque-chose comme ça. avec fetch c'est plus moderne comme façon de faire.

Bonne soirée :)

Merci juste trop top !

J'arrive à bien avancé sur ma petite appli, il me reste deux choses à faire du CSS mais sa pas de problème mais la deuxième impossible à mettre en place. Je souhaiterais que quand je selectionne la date de fin celui-ci le dernier jour soit inclus. Dans la doc de Fullcalendar il faut utilisé la propriété allDay: false mais cela n'ai pas pris en compte... voici ton(mon) code qui fonctionne avec un petit rajout car j'utilise les resources de fullcalendar (est-ce que je le place mal mon allDay):

    document.addEventListener('DOMContentLoaded', function() {
        let elementCalendrier = document.getElementById("calendar");

        fetch('http://127.0.0.1:8000/affectations_json/')
            .then(response => response.json())
            .then(evenements => {
                let calendrier = new FullCalendar.Calendar(elementCalendrier, {
                      initialView: 'resourceTimelineMonth',
                      locale: 'fr',
                      buttonText: {
                        today: 'Aujourd\'hui'
                            },
                    allDay: false,
                    events: evenements,
                      resources: 'http://127.0.0.1:8000/affectations_json/',
                      events: 'http://127.0.0.1:8000/affectations_jsonE/'
                });

                calendrier.render();
            })
            .catch(error => console.error('Erreur lors du chargement des événements:', error));
    });

Ou je me dis est-ce que dans mon fichier views.py dans ma fonction affectation_jsonE (attention au E) je peux rajouter un paramètre pour incrémenter d'un jour automatiquement pour que cela soit transparent dans l'espace administration. Voici mon code sur views :

def affectations_json(request):
    affectations = Affectation.objects.all()

    events = []
    for affectation in affectations:
        events.append({
            'id': f"{affectation.employe.nom}",
            'title': f"{affectation.employe.prenom} {affectation.employe.nom}",
        })
    return JsonResponse(events, safe=False)

def affectations_jsonE(request):
    affectations = Affectation.objects.all()

    events = []
    for affectation in affectations:
        events.append({
            'resourceId': f"{affectation.employe.nom}",
            'title': f"{affectation.chantier.nom}",
            'start': affectation.date_debut.isoformat(),
            'end': affectation.date_fin.isoformat(),
        })

    return JsonResponse(events, safe=False)

Merci pour ton aide !

Perso j'aurais tendance à l'ajouter dans la vue. Tu peux utiliser un timedelta :)

En gros tu pourrais faire quelque chose comme ça

from datetime import timedelta

def affectations_jsonE(request):
    affectations = Affectation.objects.all()

    events = []
    for affectation in affectations:
        # Incrémentation de la date de fin d'un jour
        date_fin_inclusive = affectation.date_fin + timedelta(days=1)
        events.append({
            'resourceId': f"{affectation.employe.nom}",
            'title': f"{affectation.chantier.nom}",
            'start': affectation.date_debut.isoformat(),
            'end': date_fin_inclusive.isoformat(),  # On utilise la nouvelle date de fin
        })

    return JsonResponse(events, safe=False)

Merci pour l'astuce timedelta.
Sur mon appli j'ai rajouté plein de petite chose pour m'amuser page de connection avec accès restreint, écrire sur front pour le récupéré en base de données sa fonctionne. Mais j'ai essayé de pousser un peu plus loin, en essayant de mettre à jour le planning tout en restant sur le front sans passé par le back-office (sauf pour rentré les infos qui ne bouge pas). Donc en front j'essaie de créer mes affectations mais je n'y arrive pas, je pense que c'est le faite que j'utilise ForeignKey dans ma class Affectation et du coup je dois mal rédiger ma fonction. Le but étant d'envoyer les informations dans ma BDD dans la parti Affectation pour reussir à écrire sur mon fichier JSON. Quand je regarde avec TablePlus je vois dans les cases des chiffres pour les affectation et non les valeurs mon problème dois venir de la...
le code dans front :

  <form method="post">
      {%  csrf_token %}
       <!--  <p>
            <label for="nomchantier">Nom Chantier</label>
           <input id="nomchantier" type="text" name="nomchantier">
        </p>-->
<p>
<label for="selectEmploye">Choix collaborateur:</label>
<select id="select" name="collaborateur">
<option value="">selectionné un collaborateur</option>
                    {% for choix in choixnom %}
                         <option value="{{ choix.nom }}">{{ choix.nom }} {{ choix.prenom }}</option>
                    {% endfor %}
                </select>
</p>
<p>
<label for="selectChantier">Choix chantier:</label>
<select id="selectChantier" name="Chantier">
<option value="">selectionné un chantier</option>

                    {% for choixc in choixchantier %}
                         <option value="{{ choixc.chantier }}">{{ choixc.nom }}</option>
                    {% endfor %}

                </select>
</p>
<p>
<label for="start">Date début</label>
<input id="start" max="2100-12-31" min="2024-09-01" name="trip-start" type="date" value=""/>
</p>
<p>
<label for="start">Date fin</label>
<input id="end" max="2100-12-31" min="2024-09-01" name="trip-end" type="date" value=""/>
</p>
<button type="submit">Envoyer</button>
</form>

Je remets mes models ici :
class Employe(models.Model):
    nom = models.CharField(max_length=100, unique=True, verbose_name="Nom de l'employé")
    prenom = models.CharField(max_length=100, unique=True, verbose_name="Prénom de l'employé")

    class Meta:
        unique_together = ("nom", "prenom")

    def __str__(self):
        return f"{self.nom} {self.prenom}"

class Chantier(models.Model):
    nom = models.CharField(max_length=200)

    def __str__(self):
        return self.nom

class Affectation(models.Model):
    employe = models.ForeignKey(Employe, on_delete=models.CASCADE)
    chantier = models.ForeignKey(Chantier, on_delete=models.CASCADE)
    date_debut = models.DateField(null=True)
    date_fin = models.DateField(null=True)

    def __str__(self):
        return f"{self.employe} {self.chantier}"

Voici ma fonction dans views ( j'ai concience que c'est pas super propre, j'ai essayé beaucoup de choses différente) :
def index(request):
    choixnom = Employe.objects.all()
    choixchantier = Chantier.objects.all()

    if request.method == 'POST':
        nomchantier = request.POST.get("value")
        nomchoix = request.POST.get("value")
        datedebut = request.POST.get("trip-start")
        dateend = request.POST.get("trip-end")
        Chantier.objects.create(nom=nomchantier)
        Affectation.objects.create(id=nomchoix, )
        Affectation.objects.create(employe_id=nomchoix)
        Affectation.objects.create(chantier_id=nomchantier)
        Affectation.objects.create(date_debut=datedebut)
        Affectation.objects.create(date_fin=dateend)

    return render(request, 'index.html', context={"choixnom": choixnom,
                                                               "choixchantier":choixchantier})

Merci d'avance (encore) !

Salut !

J'ai envie de faire plus simple et plus sécurisé en utilisant un django form.

Dans forms.py quelque chose comme ça :

from django import forms
from .models import Affectation

class AffectationForm(forms.ModelForm):
    class Meta:
        model = Affectation
        fields = ['employe', 'chantier', 'date_debut', 'date_fin']

Dans ta vue tu gères le form en cas de post :

from django.shortcuts import render, redirect
from .forms import AffectationForm

def index(request):
    if request.method == 'POST':
        # Si la méthode est POST, on instancie le formulaire avec les données du POST
        form = AffectationForm(request.POST)
        if form.is_valid():
            # Si le formulaire est valide, on sauvegarde les données
            form.save()
            return redirect('index')  # Rediriger vers la même page après la soumission
    else:
        # Si ce n'est pas une soumission de formulaire, on affiche un formulaire vide
        form = AffectationForm()

    # On renvoie le formulaire à la vue
    return render(request, 'index.html', {'form': form})

ça simplifie ton template html, car là ça te fais un truc du genre :

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Envoyer</button>
</form>

Je n'ai pas l'application sous les yeux, mais en faisant quelque chose comme ça, avec un form django c'est plus simple je trouve.
Si tu as besoin de personnaliser le form django c'est possible aussi :)

Merci pour ton aide, j'ai pu arrivé au bout de ce petit projet ^^

ah super ! c'est publique comme projet ?

C'est un projet qu'un ami ma demandé pour gérer son équipe.( ce qui ma permis de m'entrainé sur un vrai projet ^^ ) Tu me pose la question pour partager le projet sur docstring ? si c'est le cas sa me dérange pas du tout !

ca peut etre sympa de le présenter sur discord :)

Inscris-toi

(c'est gratuit !)

Inscris-toi

Tu dois créer un compte pour participer aux discussions.

Créer un compte

Rechercher sur le site

Formulaire de contact

Inscris-toi à Docstring

Pour commencer ton apprentissage.

Tu as déjà un compte ? Connecte-toi.