Welcome to Sign in | Help
in Search

Am nevoie de un sfat....

Last post 11-07-2008, 3:17 PM by ignatandrei. 9 replies.
Sort Posts: Previous Next
  •  11-03-2008, 4:54 PM 6010

    Am nevoie de un sfat....

    Salut, am de rezolvat urmatoarea problema: (un program acordare credit - gen banca)

    La primirea imprumutului, clientul primeste un desfasurator cu N rate lunare formata fiecare din cota din imprumut plus dobanda aferenta. Are deasemenea o data de scadenta. Pt fiecare zi de intirziere peste ziua scadentei se calculeaza x% penalizari din valoarea neachitata la timp. Clientul poate sa achite in avans una sau mai multe rate, sau poate sa plateasca o suma mai mare decit o rata dar mai mica decit 2 rate (de exemplu daca rata este de 120 RON poate achita 200RON) si atunci diferenta achitata in plus se scade din urmatoarea rata (fara a modifica dobinda!), sau mai exista cazul in care omul plateste mai putin decit valoarea unei rate (in acest caz valoarea platita se scade conform legii din dobanda lunii respective, luna viitoare calculindu-se o penalitate pt cota din rata neachitata). Ce nu mi-e clar si as dori sa ma ajutati voi cu o idee - daca eu am o tabela RATE cu campurile:
    ID_CONTRACT
    NR_RATA
    SCADENTA
    COTA
    DOBANDA
    PENALIZARE
    in care am cele 6 rate pt clientul x cu valorile corespunzatoare pt toate campurile calculate in momentul acordarii imprumutului, cum trebuie sa concep/organizez o tabela CHITANTE astfel incit sa stiu tot timpul ce anume s-a achitat cu chitanta cu numarul Y (de ex cu o chitanta se poate achita COTA + DOBANDA de pe luna decembrie + 1/2 din COTA luna ianuarie - la plata anticipata sau 1/2 din COTA lunii decembrie + DOBANDA lunii decembrie - la plata partiala)

    Sper ca am fost destul de explicit in enuntarea problemei....daca nu va stau la dispozitie!
    Multumesc anticipat
    Puiu

  •  11-03-2008, 5:06 PM 6011 in reply to 6010

    Re: Am nevoie de un sfat....

    ThePuiu:

    cum trebuie sa concep/organizez o tabela CHITANTE astfel incit sa stiu tot timpul ce anume s-a achitat cu chitanta cu numarul Y (de ex cu o chitanta se poate achita COTA + DOBANDA de pe luna decembrie + 1/2 din COTA luna ianuarie - la plata anticipata sau 1/2 din COTA lunii decembrie + DOBANDA lunii decembrie - la plata partiala)


    Dupa parerea mea , nu trebuie sa iti faci prea multe griji. In orice business, de obicei, nu se poate plati luna aprilie daca nu s-a platit luna martie(ma rog, penalizarile pot sa fie o discutie separata - trebuie sa te interesezi)

    Asa ca o reprezentare sumara ar fi :

    IDChitanta
    Numar ... <alte proprietati>

    Suma Platita pentru cota lunara
    Supa Platita pentru penalizare ( daca trebuie)

    Dupa care nu ai decit sa faci totalurile - si sa vezi ce ii ramine omului de platit ...daca vrei neaparat sa fii sigur, poti adauga
    Luna/an Pentru cota lunara
    Luna/an Pentru Penalizare



    Ignat Andrei
    http://serviciipeweb.ro/iafblog
  •  11-03-2008, 5:37 PM 6012 in reply to 6010

    Re: Am nevoie de un sfat....

    Dacă o chitanţă poate plăti mai multe rate (cu condiţia ca toate ratele să aparţină de acelaşi contract), iar o rată poate să fie plătită parţial printr-o chitanţă şi parţial prin alta, atunci înseamnă că ai o relaţie many-to-many între tabelele CHITANTE şi RATE, care poate fi reprezentată astfel:

    CREATE TABLE CHITANTE (
      NR_CHITANTA INT PRIMARY KEY,
      ID_CONTRACT INT NOT NULL REFERENCES CONTRACTE,
      SUMA_INCASATA MONEY NOT NULL,
      --UNIQUE (NR_CHITANTA, ID_CONTRACT)
    )

    CREATE TABLE PLATI_RATE (
      NR_CHITANTA INT NOT NULL REFERENCES CHITANTE,
      ID_CONTRACT INT NOT NULL REFERENCES CONTRACTE,
      -- FOREIGN KEY (NR_CHITANTA, ID_CONTRACT) REFERENCES CHITANTE (NR_CHITANTA, ID_CONTRACT),
      ID_RATA INT NOT NULL,
      FOREIGN KEY (ID_CONTRACT, NR_RATA) REFERENCES RATE (ID_CONTRACT, NR_RATA)
      VALOARE_ASOCIATA MONEY NOT NULL
    )

    Totuşi, mi se pare puţin ciudat faptul că ai pus coloanele dobândă şi penalizare în tabela RATE. După părerea mea, acolo ar trebui să fie doar valoarea ratei, iar dobânzile şi penalizările (fiind variabile, în funcţie de data curentă) ar trebui să fie calculate printr-un view sau o funcţie, nu stocate alături de datele introduse de utilizator.

    Răzvan
  •  11-03-2008, 9:51 PM 6013 in reply to 6012

    Re: Am nevoie de un sfat....

    Sint in perioada de 'conceptie', deci inca nu mi-e clar nici mie ce trebuie facut! Am ajuns si eu la concluzia ca, coloanele COTA,DOBANDA si PENALIZARE trebuie bagate in tabela CHITANTE. Poate nu inteleg eu ce vreti voi sa spuneti, dar:
    Razvan: e ok structura bazei de date, dar am impresia ca tot nu ma ajuta....
    Andrei: facind doar suma chitantelor achitate pt contractul X am impresia ca nu este suficient. Nu stiu cum se calculeaza penalizarile (algoritmul de calcul)... Instructiunile primite de la beneficiar au fost: " penalizarile se calculeaza per zi de intirziere pentru COTA+DOBANDA. Nu se calculeaza penalizari la penalizari." Poti te rog sa detaliezi putin ideea ta?

    Multumesc!

  •  11-03-2008, 9:57 PM 6014 in reply to 6013

    Re: Am nevoie de un sfat....

    ThePuiu:

    Andrei: facind doar suma chitantelor achitate pt contractul X am impresia ca nu este suficient. Nu stiu cum se calculeaza penalizarile (algoritmul de calcul)... Instructiunile primite de la beneficiar au fost: " penalizarile se calculeaza per zi de intirziere pentru COTA+DOBANDA. Nu se calculeaza penalizari la penalizari." Poti te rog sa detaliezi putin ideea ta?


    Solutia lui Razvan este cea normala, a mea este pentru cei puturosi, care vor rapid aplicatia functionala.
    Sa detaliez ce vroiam sa spun : intrebi beneficiarul : sa zicem ca cineva intirzie martie si aprilie.In mai vrea sa plateasca
    Intrebare 1: are voie sa plateasca aprilie(partial sau nu) fara sa plateasca martie INTEGRAL ? - 99,9% - NU
    Intrebare 2: are voie sa plateasca martie si aprilie fara sa plateasca penalizari ? 75% nu - plateste martie , penalizarea pentru martie, partial aprilie din ceea ce mai ramine ...
    Punind intrebarile acestea si primind raspuns, poti dezvolta mai repede aplicatia ( constringeri benefice ...)

    Ignat Andrei
    http://serviciipeweb.ro/iafblog
  •  11-06-2008, 12:00 PM 6079 in reply to 6012

    Re: Am nevoie de un sfat....

    rsocol:
    Dacă o chitanţă poate plăti mai multe rate (cu condiţia ca toate ratele să aparţină de acelaşi contract), iar o rată poate să fie plătită parţial printr-o chitanţă şi parţial prin alta, atunci înseamnă că ai o relaţie many-to-many între tabelele CHITANTE şi RATE, care poate fi reprezentată astfel:

    CREATE TABLE CHITANTE (
      NR_CHITANTA INT PRIMARY KEY,
      ID_CONTRACT INT NOT NULL REFERENCES CONTRACTE,
      SUMA_INCASATA MONEY NOT NULL,
      --UNIQUE (NR_CHITANTA, ID_CONTRACT)
    )

    Nu înţeleg de ce ai în CHITANŢĂ cheia externă ID_CONTRACT ?

    Deci ID_CONTRACT este cheie externă şi în RATĂ, şi în PLATA_RATA şi în CHITANŢĂ ?!

    rsocol:

    CREATE TABLE PLATI_RATE (
      NR_CHITANTA INT NOT NULL REFERENCES CHITANTE,
      ID_CONTRACT INT NOT NULL REFERENCES CONTRACTE,
      -- FOREIGN KEY (NR_CHITANTA, ID_CONTRACT) REFERENCES CHITANTE (NR_CHITANTA, ID_CONTRACT),
      ID_RATA INT NOT NULL,
      FOREIGN KEY (ID_CONTRACT, NR_RATA) REFERENCES RATE (ID_CONTRACT, NR_RATA)
      VALOARE_ASOCIATA MONEY NOT NULL
    )

    Nu înţeleg de ce ai definit cheia externă ID_CONTRACT (ID_CONTRACT INT NOT NULL REFERENCES CONTRACTE) din moment ce ai definit şi cheia externă ID_CONTRACT + NR_RATA (FOREIGN KEY (ID_CONTRACT, NR_RATA) REFERENCES RATE (ID_CONTRACT, NR_RATA)
    ) ?

    Şi în cazul acesta (tabela PLATI_RATE propusă de tine) cum este rezolvată cerinţa: "Clientul poate sa achite in avans una sau mai multe rate, sau poate sa plateasca o suma mai mare decit o rata dar mai mica decit 2 rate" ? Diferenţa dintre suma paltita şi suma ratei ?

  •  11-07-2008, 8:39 AM 6094 in reply to 6079

    Re: Am nevoie de un sfat....

    B_gd_n[ ]Sahlean:

    Nu înţeleg de ce ai în CHITANŢĂ cheia externă ID_CONTRACT ?

    Trebuie să spun cine a plătit acea sumă. Dacă nu aş fi avut ID_CONTRACT, aş fi avut ID_CLIENT, însă am impresia că atunci când se achită o sumă, se precizează exact la ce contract se referă (nu doar clientul), aşa că am preferat să ţin doar ID_CONTRACT, iar ID_CLIENT se poate regăsi din tabela CONTRACTE.

    B_gd_n[ ]Sahlean:

    Deci ID_CONTRACT este cheie externă şi în RATĂ, şi în PLATA_RATA şi în CHITANŢĂ ?!

    Prin această cheie externă, asigur regula de business care spune că o chitanţă poate plăti doar ratele aferente acelui contract. Motivul care m-a făcut să aleg această soluţie a fost faptul că am avut impresia că primary key-ul din tabela RATE este compus din ID_CONTRACT+NR_RATA, deci dacă vroiam să fac un foreign key în tabela PLATA_RATA către tabela RATE, oricum trebuia să includ coloana ID_CONTRACT şi dacă tot o am şi în tabela CHITANTE, atunci pun şi foreign key-ul (care era comentat) ca să mai acopăr o regulă de business.

    Oricum, dacă n-ar fi fost ID_CONTRACT, ar fi fost ID_Client, şi tot ar fi trebuit să asigur regula că o chitanţă poate plăti doar facturile aceluiaşi client. De exemplu, în cazul clasic, avem:

    CREATE TABLE Facturi (
      ID_Factura int IDENTITY PRIMARY KEY,
      ID_Client int NOT NULL REFERENCES Clienti,
      DataFactura smalldatetime NOT NULL,
      NumarFactura varchar(10) NOT NULL UNIQUE,
      TotalFactura money NOT NULL
    )

    --CREATE TABLE DetaliiFacturi ...

    CREATE TABLE Chitante (
      ID_Chitanta int IDENTITY PRIMARY KEY,
      ID_Client int NOT NULL REFERENCES Clienti,
      DataChitanta smalldatetime NOT NULL,
      NumarChitanta varchar(10) NOT NULL UNIQUE,
      SumaIncasata money NOT NULL
    )

    CREATE TABLE Asocieri (
      ID_Factura int REFERENCES Facturi,
      ID_Chitanta int REFERENCES Chitante,
      ValoareAsociere money NOT NULL,
      PRIMARY KEY (ID_Factura, ID_Chitanta)
    )

    În acest caz, trebuie să verific prin trigger-e că asocierile se fac doar între facturi şi chitanţe care aparţin aceluiaşi client. Dacă adaug şi coloana ID_Client în tabela Asocieri, atunci această verificare poate fi făcută declarativ, nu procedural (porţiunile adăugate sunt marcate apăsat):

    CREATE TABLE Facturi (
      ID_Factura int IDENTITY PRIMARY KEY,
      ID_Client int NOT NULL REFERENCES Clienti,
      DataFactura smalldatetime NOT NULL,
      NumarFactura varchar(10) NOT NULL UNIQUE,
      TotalFactura money NOT NULL,
      UNIQUE (ID_Client, ID_Factura)
    )

    --CREATE TABLE DetaliiFacturi ...

    CREATE TABLE Chitante (
      ID_Chitanta int IDENTITY PRIMARY KEY,
      ID_Client int NOT NULL REFERENCES Clienti,
      DataChitanta smalldatetime NOT NULL,
      NumarChitanta varchar(10) NOT NULL UNIQUE,
      SumaIncasata money NOT NULL
      UNIQUE (ID_Client, ID_Chitanta)
    )

    CREATE TABLE Asocieri (
      ID_Factura int REFERENCES Facturi,
      ID_Chitanta int REFERENCES Chitante,
      ID_Client int REFERENCES Clienti,
      ValoareAsociere money NOT NULL,
      PRIMARY KEY (ID_Factura, ID_Chitanta),
      FOREIGN KEY (ID_Client, ID_Factura) REFERENCES Facturi (ID_Client, ID_Factura),
      FOREIGN KEY (ID_Client, ID_Chitanta) REFERENCES Facturi (ID_Client, ID_Chitanta)
    )

    E adevărat, e vorba de o denormalizare a tabelei Asocieri: coloana ID_Client are o dependenţă funcţională faţă de ID_Factura (sau faţă de ID_Chitanta), care nu este cheia primară (ci doar o parte din aceasta). Are şi dezavantaje: ce facem dacă se modifică clientul unei chitanţe ? În oricare din cele două variante, trebuie să ştergem toate asocierile (sau să interzicem modificarea), pentru că nu pot rămâne asocieri cu facturi ale altui client. Dar în această variantă, nu putem să facem ştergerea printr-un trigger normal, pentru că foreign key-ul se verifică înainte de trigger-ele AFTER, deci trebuie să facem un trigger INSTEAD OF, ceea ce e un pic mai neplăcut. Are şi alte avantaje (în afară de eliminarea trigger-ului menţionat): dacă te interesează toate asocierile pentru un anumit client, poţi să iei direct datele din tabela Asocieri, nu mai trebuie să faci join cu Facturi sau cu Chitante. Deci e discutabil care dintre cele două variante e preferabilă...

    B_gd_n[ ]Sahlean:

    Nu înţeleg de ce ai definit cheia externă ID_CONTRACT (ID_CONTRACT INT NOT NULL REFERENCES CONTRACTE) din moment ce ai definit şi cheia externă ID_CONTRACT + NR_RATA (FOREIGN KEY (ID_CONTRACT, NR_RATA) REFERENCES RATE (ID_CONTRACT, NR_RATA)
    ) ?

    Din punctul de vedere al asigurării integrităţii, într-adevăr această cheie este redundantă. Totuşi, am adăugat-o din două motive:

    1. Documentarea bazei de date (atunci când vreau să găsesc toate coloanele care se referă la contracte, pot să fiu sigur că le găsesc pe toate).

    2. Poate fi util pentru query optimizer, care ar putea să se bazeze pe acest foreign key ca să mai optimizeze unele query-uri (vezi aici).

    B_gd_n[ ]Sahlean:

    Şi în cazul acesta (tabela PLATI_RATE propusă de tine) cum este rezolvată cerinţa: "Clientul poate sa achite in avans una sau mai multe rate, sau poate sa plateasca o suma mai mare decit o rata dar mai mica decit 2 rate" ? Diferenţa dintre suma paltita şi suma ratei ?



    Păi, simplu... (sau poate nu înţeleg întrebarea): de exemplu, dacă avem chitanţa nr. 111 pentru suma de 230 lei şi ratele nr.1, nr.2, nr.3 şi nr.4  fiecare de câte 100 lei, atunci în tabela CHITANTE avem (simplific, pentru claritate):

    Nr_Chitanta   Suma_Incasata
    111              230

    iar în tabela PLATI_RATE avem (de asemenea, simplificat):

    Nr_Chitanta   Nr_Rata        Valoare_Asociere
    111              1                  100
    111              2                  100
    111              3                  30

    Iar apoi dacă avem chitanţa nr. 222 pentru suma de 170 lei, atunci mai adăugăm:

    Nr_Chitanta   Nr_Rata        Valoare_Asociere
    222              3                  70
    222              4                  100

    Ar trebui să mai avem ceva care ne asigură că SUM(Valoare_Asociere) GROUP BY Nr_Chitanta este egal cu Suma_Incasata, dar acest lucru nu se poate face prin trigger-e, deci va trebui verificat la sfârşit (după ce sunt adăugate toate datele).

    Răzvan
  •  11-07-2008, 11:40 AM 6097 in reply to 6094

    Re: Am nevoie de un sfat....

    rsocol:
    B_gd_n[ ]Sahlean:

    Nu înţeleg de ce ai în CHITANŢĂ cheia externă ID_CONTRACT ?

    Trebuie să spun cine a plătit acea sumă. Dacă nu aş fi avut ID_CONTRACT, aş fi avut ID_CLIENT, însă am impresia că atunci când se achită o sumă, se precizează exact la ce contract se referă (nu doar clientul), aşa că am preferat să ţin doar ID_CONTRACT, iar ID_CLIENT se poate regăsi din tabela CONTRACTE.


    Aş vedea utilitatea unei chei externe ID_CLIENT în CHITANŢĂ atunci când plăţile ar putea fi realizate şi de către alte persoane decât acel client care a obţinut [contractul de] credit[ul].
    Din ce a povestit ThePuiu eu înţeleg că aceste plăţi pot fi realizate [doar] de către client[ul contractului]. Dacă avem în vedere şi regula de gestiune "o chitanţă poate plăti doar ratele aferente acelui contract" atunci avem NR_CHITANTA -> NR_CONTRACT -> ID_CLIENT. În concluzie NR_CHITANTA -t -> ID_CLIENT.
  •  11-07-2008, 2:44 PM 6098 in reply to 6097

    Re: Am nevoie de un sfat....

    intr-un final am hotarit sa merg pe varianta simpla (babeasca) pe care a sugerat-o Andrei, adica sa fac suma suma chitantelor anterioare. Sper sa nu dau peste alte inconveniente pe parcurs din cauza acestei abordari... Toate aceste probleme ridicate au aparut din cauza ca am incercat sa prevad toate situatiile posibile...desi clientul si-a facut cruce cind a auzit ce vreau sa fac si m-a 'linistit' ca nici 50% din potentialele variante nu vor exista in practica! Dar eu sint patit si ma astept ca oricind (dupa un an de la predare!) sa isi dea seama ca vor de fapt si altceva! Aste e viata...

    Multumesc mult pt implicarea in problema mea!
    Puiu

  •  11-07-2008, 3:17 PM 6099 in reply to 6098

    Re: Am nevoie de un sfat....

    ThePuiu:

    Dar eu sint patit si ma astept ca oricind (dupa un an de la predare!) sa isi dea seama ca vor de fapt si altceva! Aste e viata...


    Asta e norocul nostru ... gindeste-te ca nimeni de la business nu ar mai vrea nimic ... As da faliment ...

    Ignat Andrei
    http://serviciipeweb.ro/iafblog
View as RSS news feed in XML
Powered by Community Server (Commercial Edition), by Telligent Systems