Bonjour
La première question à se poser est : As-tu vraiment besoin que le solde soit stocké dans la base de données ?
Par ce que le solde, c'est le résultat d'une somme. Donc ça peut n'être géré qu'à l'affichage.
La deuxième question à se poser est : Dans la base de données, est-il nécessaire d'avoir un champ dépense et un champ recette, car dans les 2 cas, c'est un mouvement qui est soit positif, soit négatif.
Et donc pareil, la séparation en 2 colonnes peut très bien n'être gérée qu'à l'affichage.
whismeril supposons que je fasse à ta manière, c'est à dire ne gérer le solde de la caisse qu'à l'affichage, comment pourrais-je m'en prendre en sql?
En sql je ne sais pas, mais avec Linq je sais.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionTu écris une classe métiers dont tous les champs de ta base sont transcrits en propriétés en lecture et écriture.
Tu ajoutes 2 propriétés en lecture et écriture
Et une propriété en lecture seule
Recette affiche 0 ou null, si mouvement est négatif et la valeur du mouvement s'il est positif
Dépense affiche l'inverse.
Quand elles sont éditées, ces propriétés mettent à jour la propriété mouvement.
Quand mouvement est modifié (ta classe pourrait implémenter INotifyPropertyChanged {d'ailleurs si tu utilises le binding c'est déjà fait} ou alors, tu peux créer un événement spécifique), il faut mettre à jour toutes les instances suivantes.
Un simple For devrait suffire. Mais on peut faire une requette linq.
En y réfléchissant, si tu fais en sorte que tes instances soient chainées, y'a p'tet même pas besoin de For.
Je peux te faire un exemple sur la base d'un csv soit en winform, soit en WPF, à toi de me dire
Bon, sans réponse de ta part et ayant un peu de temps là, mais plus après, voilà un exemple en winform
D'abord le fichier CSV
2022/01/01 12:00:00;Ouverture du compte;1000 2022/01/01 14:00:00;Courses;-150 2022/01/02 8:00:00;Carburant;-100 2022/01/03 13:00:00;Etrennes;200
Ensuite la classe métier
Imports System.ComponentModel Namespace WindowsFormsApp1 Friend Class Transaction Implements INotifyPropertyChanged Private datationField As Date ''' <summary> ''' Date et heure de la transaction ''' </summary> Public Property Datation As Date Get Return datationField End Get Set(ByVal value As Date) If datationField = value Then Return datationField = value 'On signale le changement de la datation GenerePropertyChanged("Datation") End Set End Property Private libelleField As String ''' <summary> ''' Libellé de la transaction ''' </summary> Public Property Libelle As String Get Return libelleField End Get Set(ByVal value As String) If Equals(libelleField, value) Then Return libelleField = value 'on signale le changement du libellé GenerePropertyChanged("Libelle") End Set End Property Private mouvementField As Double ''' <summary> ''' Mouvement de la transaction ''' </summary> Public Property Mouvement As Double Get Return mouvementField End Get Set(ByVal value As Double) If mouvementField = value Then Return mouvementField = value 'On signale le changement du mouvement de tout ce qui en dépend GenerePropertyChanged("Mouvement", "Recette", "Depense", "Solde") End Set End Property ''' <summary> ''' Recette si c'est le cas ''' </summary> Public Property Recette As Double Get Return If(Mouvement > 0, Mouvement, 0) End Get Set(ByVal value As Double) Mouvement = value End Set End Property ''' <summary> ''' Dépense si c'est le cas ''' </summary> Public Property Depense As Double Get Return If(Mouvement < 0, -1 * Mouvement, 0) End Get Set(ByVal value As Double) Mouvement = -1 * value End Set End Property Private soldePrecedent As Double = 0 ''' <summary> ''' Solde => Solde précédent + mouvement de cette instance ''' </summary> Public ReadOnly Property Solde As Double Get Return soldePrecedent + mouvementField End Get End Property ''' <summary> ''' Met à jour le solde précédent quand il a changé ''' </summary> ''' <param name="LeSoldePrecedent"></param> Public Sub MajSoldePrecedent(ByVal LeSoldePrecedent As Double) soldePrecedent = LeSoldePrecedent GenerePropertyChanged("Solde") End Sub ''' <summary> ''' Méthode abonnée aux changements de la transaction précédente ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> Private Sub Precedente_PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) If Equals(e.PropertyName, "Solde") Then GenerePropertyChanged("Solde") ' si le solde précédent a changé, on signale que celui-ci change aussi End Sub ''' <summary> ''' Méthode permettant de signaler la mise à jour de certaines valeurs ''' </summary> ''' <param name="NomsProprietes"></param> Private Sub GenerePropertyChanged(ParamArray NomsProprietes As String()) For Each nom In NomsProprietes RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(nom)) If nom = "Solde" Then RaiseEvent SoldeChanged(Me) Next End Sub ''' <summary> ''' Implémentation de INotifyPropertyChanged, pour la mise à jour du binding ''' </summary> Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged ''' <summary> ''' Evènement qui signale que le solde a changé et donc qu'il faut recalculer l'instance suivante ''' </summary> ''' <param name="sender"></param> Public Event SoldeChanged(ByVal sender As Transaction) End Class End Namespace
Et le code dans le formulaire
Private lesTransactions As BindingList(Of Transaction) 'liste de Transactions à binder Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) 'Lecture du fichier csv pour construire la liste de Transactions Dim datasCSV = File.ReadAllLines("exemplegeekmtl.csv") lesTransactions = New BindingList(Of Transaction)() Dim soldePrecedent As Double = 0 For Each ligne In datasCSV Dim datas = ligne.Split(";"c) Dim nouvelle As Transaction = New Transaction With { .Datation = Date.Parse(datas(0)), .Libelle = datas(1), .Mouvement = Double.Parse(datas(2)) } nouvelle.MajSoldePrecedent(soldePrecedent) lesTransactions.Add(nouvelle) AddHandler nouvelle.SoldeChanged, AddressOf Transaction_SoldeChanged ' on s'abonne à l'évènement pour savoir quand mettre à jour l'instance suivante soldePrecedent = nouvelle.Solde Next transactionBindingSource.DataSource = lesTransactions 'binding sur un BindingSource configuré pour ne pas afficher le mouvement End Sub Private Sub Transaction_SoldeChanged(ByVal sender As Transaction) 'le solde de l'instance "sender" a changé, il faut mettre à jour la suivante Dim indexEncours = lesTransactions.IndexOf(sender) If indexEncours < lesTransactions.Count - 1 Then 'on met à jour le solde de la suivante lesTransactions(indexEncours + 1).MajSoldePrecedent(sender.Solde) 'ça va déclencher l'évènement de cette instance et donc revenir ici pour faire faire la mise à jour de la suivante, etc. … End If End Sub
Au démarrage
Après avoir mis à jour une recette (idem pour une dépense)
Je n'ai pas géré l'ajout (ou l'insertion) ni la suppression d'une transaction, mais dans un cas comme dans l'autre, il faudra déclencher une mise à jour du solde de la suivante.
Ce code là c'est du grand Whismeril !
:)