IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Modélisation Discussion :

Probleme design: compte avec historique et validité


Sujet :

Modélisation

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Probleme design: compte avec historique et validité
    Hello tout le monde

    Je dois concevoir un système et y a un composant qui me pose probleme.
    Ce composant doit être capable de gérer un compte, un peu comme un compte de crédit: vous alimenter votre compte, p.ex. 50 crédit, mais ces crédit ont une durée de validité. Une fois cette periode passée, ce qui reste est perdu.

    Autres règles:
    - Je dois pouvoir avoir la balance du compte à n'importe quelle date (donc pouvoir dire qu'au 5/01/2010 la balance était de XX) et cette fonctionnalité sera quasiment autant utilisée que connaitre la balance "aujourd'hui"
    - des modifications peuvent être faite dans le passé comme dans le futur. Càd qu'aujourd'hui, un process peut tourner et aller insérer/supprimer des crédit à la date du 21/09/2009 ou même dans le futur.
    - Quand des crédits sont utilisés sur ce compte, les crédit avec une fin de validité la plus proche doivent être décomptés en 1er.
    - Il doit être possible de rajouter des crédits sans date de validité (= toujours valide) et ça sera même l'utilisation principale.

    Mon 1er design est très simple:
    - 1 objet account (qui stocke les differents compte)
    - 1 objet account_detail (qui stocke les mouvements du compte)

    La balance d'un compte est toujours calculée dynamiquement (somme des details where date_detail <= date_demandée). Ca va fonctionner nickel pour les mouvements toujours valides.

    Là où je bloque ... c'est comment implémenter la validité.
    Exemple:

    01/01/2009 +50cr (validité: 1 mois) --> balance: +50
    06/01/2009 -15cr ---> balance: +35
    18/01/2009 +20cr (validité: 5 jours) --> balance: +40
    20/01/2009 -30cr ---> balance: +10
    25/01/2009 -10cr --> REFUSE

    La derniere transaction est refusée, car les 10cr restant au 20/01 venait du +20cr du 18/01 qui n'avait qu'une validité de 5jours, et donc le 25/01 les 10cr restant ne sont plus valides.
    Et donc si je demande au systeme la balance au 22/01 il me dira +10cr (toujours valides), mais si je lui demande la balance au 23/01 il me dira 0cr.

    Si vous avez des pistes, merci d'avance!

  2. #2
    Membre averti Avatar de welcome_59
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2007
    Messages : 203
    Points : 352
    Points
    352
    Par défaut
    Je ne suis pas certain d'avoir bien compris, mais ça me semble faisable via une fonction xSQL, qui fonctionnerait comme suit.

    Si la différence entre la date actuelle et la date de dernière mise à jour du crédit (stockée) est supérieure à la durée de validité (stockée aussi), alors tu renvoies 0.

    Tu peux aussi stocker le crédit actuel et mettre à jour à chaque accès au compte (attention aux questions de performances).

    Ou éventuellement passer par un trigger. Mais ça me semble beaucoup trop tordu.

  3. #3
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Si j'ai bien tout compris, tu as les besoins suivants :

    * ajouter des crédits à une date donnée, qui sont valides pour une durée donnée
    * calculer le solde du compte à une date donnée
    * retirer des crédits à une date donnée, en prenant soin de retirer d'abord les crédits les plus anciens

    J'y vois trois classes (et peut-être des petites classes utilitaires) - en pseudo code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    class compte
      attribut liste<credit> credits
      fonction ajouter(credit c)
    
      fonction booléen retirer(monnaie m) {
        if (solde() < m) return faux
    
        trie_par_date_fin_validite(credits);
        foreach (credit c : credits) {
          if (c.est_valide()) {
            m = c.retirer(m)
            if (m == 0) break
          }
        }
        supprimer_credits_vides()
        return vrai
      }  
    
      fonction monnaie solde() {
        monnaie s = 0
        foreach(credit c : credits) {
          if (c.est_valide()) {
            s += c.solde()
          }
        }
        return s
      }
    
    class credit
      attribut monnaie somme
      attribut condition_validite validite
      fonction booléen est_valide()
      fonction monnaie solde()
      fonction monnaie retirer(monnaie m) {
        if (m > somme) {
          result = m - somme
          somme = 0
          return result
        } else {
          somme -= m;
          return 0;
        }
      }
    
    class condition_validite
      fonction booléen est_valide()
      fonction date fin_validite()
    
    class monnaie -> classe utilitaire qui se comporte comme un entier
    Le principe consiste donc, selon moi, à encapsuler la notion de fin de validité dans la notion de crédits.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2009
    Messages : 6
    Points : 6
    Points
    6
    Par défaut
    Un grand merci pour vos messages et désolé pour la réponse un peu tardive (je comptais sur les notifications mais je ne reçois rien)
    Merci aussi pour le pseudo code, je m'était plus orienté "maniere de faire pour pouvoir calculer directement dans la query SQL" mais à mon avis c'est en effet impossible à faire...

    Mais sinon, le plus gros problème vient des "recalculs" cad si on va dans le passé et qu'on fait une modification
    Imaginons notre cas de départ légèrement modifié:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    01/01/2009 +50cr (validité: 1 mois) --> balance: +50
    06/01/2009 -15cr ---> balance: +35
    18/01/2009 +20cr (validité: 5 jours) --> balance: +40
    19/01/2009 +10cr (validité: 5 jours) --> balance: +50
    20/01/2009 -30cr ---> balance: +20
    24/01/2009 -10cr --> ACCEPTE (grace au +10 du 19/01 qui est toujours valide)
    Si maintenant on retourne dans le passé et on supprime le +10cr du 19/01, comment savoir que le 24/01 n'es plus valide ?
    Actuellement, j'ai beau chercher mais je ne vois qu'une solution: recalculer tout après la date de modification

    Ou alors de lier d'une quelconque maniere la modif "-10cr.24/01" au mouvement "+10cr.19/01", de telle sorte que quand on supprime un mouvement on doivent recalculer les mouvements liés. Mais la répercussion peut se faire en cascade et donc à mon avis y a pas moyen de détecter ce qui doit être recalculé
    Quand je dis en cascade cad par exemple que "-X" est lié à "+Y". Mais si on supprime "+Y", après recalcul on a "-X" qui est maintenant lié à "+Z". Mais il se peut alors que "+Z" est entièrement "utilisé", et "-K" qui était avant lié à "+Z" n'est plus valide et doit donc être recalculé. Donc si on fait un lien, lors d'une modification il doit être récursivement suivit (le lien "+Y"/"-X", puis "+Z"/"-K", etc) ... ca devient compliqué tout ça...

    Bref je cherche une solution simple, mais je ne sais pas si elle existe...

  5. #5
    ego
    ego est déconnecté
    Rédacteur

    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juillet 2004
    Messages
    1 883
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2004
    Messages : 1 883
    Points : 3 510
    Points
    3 510
    Billets dans le blog
    2
    Par défaut
    ben moi je ne vois pas de solution simple puisqu'il y a une logique "complexe" de recalcul en cascade à plusieurs niveaux

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 426
    Points : 37 008
    Points
    37 008
    Par défaut
    Bonsoir,
    Si maintenant on retourne dans le passé et on supprime le +10cr du 19/01, comment savoir que le 24/01 n'es plus valide ?
    Actuellement, j'ai beau chercher mais je ne vois qu'une solution: recalculer tout après la date de modification
    Idée: La balance au 24/01 est de +10, si vous supprimez le +10 du 19/01 elle deviendra 0.
    si on fait +/-X dans le passé sur une durée D
    on peut regarder ce que deviennent les balancent des transactions (TX) suivantes sur la durée D et s'assurer qu'elles restent >0.
    Autrement dit l'ensemble des TX dont la date est dans [J0..J0+D] et la balance +/-X > 0.
    -W

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    83
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 83
    Points : 95
    Points
    95
    Par défaut
    Bonsoir,

    Dans l'énoncé de la question, il est dit :

    La balance d'un compte est toujours calculée dynamiquement (somme des details where date_detail <= date_demandée). Ca va fonctionner nickel pour les mouvements toujours valides.

    Là où je bloque ... c'est comment implémenter la validité.
    et aussi :
    Je dois pouvoir avoir la balance du compte à n'importe quelle date (donc pouvoir dire qu'au 5/01/2010 la balance était de XX)
    En vision "statique", le calcul d'un solde s'apparente aux calculs de base de comptabilité, date de fin de validité mise à part. Et puisque le deal de base est de calculer le solde à partir des détails, naïvement, j'aurais créé une table avec
    date de création du crédit (ou de l'annulation ou de l'imputation au crédit), date de début du crédit, date de fin, montant.

    Cela rejoint un peu la proposition faite par E. Deloget en termes littéraires. Les calculs paraissent simples : additionner tous les montants dont la date de début est antérieure et la date de fin postérieure au jour de la date souhaitée.

    En version "dynamique", il y a un point que je n'ai pas saisi, dans les règles de gestion, et qui est : si il y a un mois le solde était de 0, et que aujourd'hui je rajoute un crédit de 100 avec début de valeur il y a un mois; quel est le résultat attendu sur une interrogation du solde il y a un mois : l'image telle qu'elle était il y a un mois (c'est-à-dire zéro) ou bien la valeur vue a posteriori (100)?

    Supposons que la règle soit la seconde réponse. Il suffit le conserver la règle "statique". Si la règle est la première réponse, il faut alors tenir compte de la date d'imputation, et faire une sélection préalable de plus sur date d'imputation inférieure ou égale à date souhaitée pour l'interrogation.

    Au total, 3 select de date en base de données. A optimiser si la rétroactivité est limitée dans le temps.

    Bien sur, pour que cela fonctionne, il faut que les utilisations (débits) soient entrés en montant signés négatifs, avec date de début et date de fin la date du jour dans le cas le plus simple. (ou date de valeur par exemple dans le cas de calcul d'échelles d'intérêts bancaires).

    En ce qui concerne les crédits à durée illimitée, une solution pour assurer un job à nos arrières petits enfants seraient de valoriser la date de fin à 2099. Quoiqu'il y ait certainement des façons plus élégantes ; mais elles impliquent de savoir interpréter des dates nulles comme étant postérieures.

    Bon, tout ceci me semble trop simple par rapport à votre question initiale et aux réponses (triggers, recalculs en cascade, etc...). J'ai du louper un détail, mais je n'arrive pas à trouver lequel. Merci de votre retour quand vous aurez résolu le point!

Discussions similaires

  1. [OL-2003] probleme de compte avec Outlook 2003
    Par pepsyx dans le forum Outlook
    Réponses: 2
    Dernier message: 23/12/2009, 20h53
  2. Réponses: 16
    Dernier message: 26/05/2009, 19h17
  3. Réponses: 2
    Dernier message: 22/01/2008, 22h39
  4. Problem sous IE avec design 2 colonnes + Entête
    Par Erakis dans le forum Mise en page CSS
    Réponses: 6
    Dernier message: 27/07/2007, 15h43

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo