Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions DDD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
## Domain Driven Design - Adam Zientek



### 1. Opis bounded-context

Aplikacja mobilna bankowa pozwala Klientowi indywidualnemu na:

* zarządzanie swoimi danymi - edycja danych osobowych, usunięcie swoich danych z banku (i zamknięcie wszystkich rachunków),
* zarządzanie kontem - zamknięcie, otworzenie, edycja konta,
* wykonywanie przelewów,
* podgląd transakcji - przelewów i płatności kartą,
* zarządzanie kartami debetowymi/kredytowymi - zamówienie karty, zablokowanie/usunięcie karty,
* uwierzytelnienie w aplikacji (w encji Klient nie ma atrybutu hasło, ponieważ aplikacja w celu weryfikacji hasła komunikuje się z zewnętrznym Bankowym systemem uwierzytelniania - chcę uniknąć przechowywania hasła klienta w aplikacji mobilnej nawet w postaci hashu).





### 2. Diagram

Legenda:

ostre kąty - encje

zaokrąglone rogi - obiekty wartości



![Diagram](ddd.png)



### 3. Opis encji i obiektów wartości



### Encje:

**Customer** - opisuje klienta Banku. Klient jest rozumiany jako osoba fizyczna (w tym przypadku nie rozważam klientów będących np. firmą). Klient posiada następujące atrybuty:

* **Customer\_id** - String (dokładnie 6 cyfr) - służy do logowania klienta i jego identyfikacji w Banku,
* **Names** - String (max 100 znaków) imię lub imiona klienta,
* **Last\_name** - String (max 50 znaków) nazwisko klienta,
* **Address** - obiekt wartości (opisany później) - adres zamieszkania klienta,
* **ID\_number** - String (dokładnie 9 znaków - 3 litery + 6 cyfr) - numer dowodu klienta,
* **Pesel** - String (dokładnie 11 cyfr) - numer Pesel klienta,
* **Email** - String (max 30 znaków - według standardowego regexu adresu email) - adres email klienta,
* **Phone** - Obiekt, składający się z Region (Obiekt wartości jako String max 5 znaków z kodem regionu np. +48) i phone\_number (String max 11 znaków) - nr telefonu klienta
* **Status** - Obiekt wartości ze stringami: "Active", "Disactivated".



**Transaction** - transakcje na koncie klienta, reprezentuje same zmiany na koncie, nie cały zapis transakcji:

* **Type** - Obiekt wartości ze stringami "Card", "Bank\_transfer",
* **Account\_id** - String (dokładnie 26 cyfr) numer konta bankowego,
* **Transfer\_id** - tylko jeśli Type==Bank\_transfer; id dokonanego przelewu,
* **Payment\_id** - tylko jeśli Type==Card; id płatności kartą,
* **Difference** - Signed float - różnica w saldzie konta przez transakcję
* **Post\_trans\_saldo** - Signed float - saldo konta po operacji,
* **Currency** - waluta transakcji,
* **Date** - format datetime - data i godzina transakcji.



**Bank\_transfer** - encja reprezentuje przelew bankowy

* **Transfer\_id** - String (dokładnie 20 znaków) id dokonanego przelewu,
* **Sender\_account\_id** - String (dokładnie 26 cyfr) numer konta bankowego nadawcy,
* **Recipient\_account\_id -** String (dokładnie 26 cyfr) numer konta bankowego odbiorcy,
* **Amount** - obiekt składający się z: obiektu wartości Currency (kod 3 znaki) i value (float) - wartość transakcji (jej wpływ na konto poznajemy przez encję Transaction),
* **Title -** String (max 60 znaków) - tytuł przelewu.



**Card\_transfer -** encja reprezentująca płatność kartą

* **Payment\_id -** String (dokładnie 20 znaków) id płatności,
* **Type** - obiekt wartości - Online, Touch, Standard - rodzaj transkacji kartą,
* **Card\_id** - String (dokładnie 16 cyfr) numer karty użytej do płatności,
* **Recipient\_name** - String (max 30 znaków) nazwa odbiorcy płatności (w przypadku zwrotu - płatnika),
* **Recipient\_ref\_id** - String (dokładnie 16 znaków) - numer referencyjny odbiorcy/płatnika,
* **Amount** - ten sam obiekt co w Bank\_transfer.



**Account** - encja reprezentująca konto bankowe

* **Account\_id** - String (dokładnie 26 cyfr) numer konta bankowego,
* **Account\_type -** obiekt wartości - enum z typami konta np. Savings, Credit,
* **Client\_ids** - lista id klientów (bo może być współdzielone),
* **Saldo** - Signed float - saldo konta,
* **Currency** - obiekt wartości z kodem waluty używanej na koncie,
* **Status -** obiekt wartości ze stringami: "Active", "Disactivated",
* **Create date** **-** datetime, data utworzenia konta.



**Card** - encja reprezentująca kartę przypisaną do konta:

* **Card\_id** - String (dokładnie 16 cyfr) - numer karty,
* **Account\_id** - numer konta z encji Account,
* **Expiry\_date** - String (dokładnie 5 znaków - format MM/YY) - miesiąc, w którym karta przestanie działać
* **Card\_type** - obiekt wartość z typem karty Debit lub Credit,
* **Daily\_limit** - Currency + limit\_value jako unsigned float - dzienna kwota limitu transakcji,
* **Status -** obiekt wartości ze stringami: "Active", "Disactivated",
* **Available\_funds** - unsigned float - dostępne środki na karcie.



### Obiekt wartości Address:

* Street - String (max 100)
* Building\_no - String (max 8)
* Apartment\_no - opcjonalny String (max 6)
* City - String (max 50)
* Postal\_code - String (format: XX-XXX)
* Country - String (max 30)
25 changes: 22 additions & 3 deletions Python/Flask_Book_Library/project/books/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from project import db, app
from markupsafe import escape
import re


Expand All @@ -13,12 +14,30 @@ class Book(db.Model):
status = db.Column(db.String(20), default='available')

def __init__(self, name, author, year_published, book_type, status='available'):
self.name = name
self.author = author
#na potrzeby weryfikacji w zadaniu funkcja escape jest używana tylko wtedy gdy wykryte są specjalne znaki
if self.contains_special_chars(name):
self.name = escape(name)
else:
self.name = name

if self.contains_special_chars(author):
self.author = escape(author)
else:
self.author = author

self.year_published = year_published
self.book_type = book_type
if self.contains_special_chars(book_type):
self.book_type = escape(book_type)
else:
self.book_type = book_type
self.status = status

@staticmethod
def contains_special_chars(value: str) -> bool:
"""
Sprawdzenie, czy w stringu są znaki specjalne sugerujące wstrzyknięcie.
"""
return bool(re.search(r"[<>&\"'/-;]", value))
def __repr__(self):
return f"Book(ID: {self.id}, Name: {self.name}, Author: {self.author}, Year Published: {self.year_published}, Type: {self.book_type}, Status: {self.status})"

Expand Down
20 changes: 18 additions & 2 deletions Python/Flask_Book_Library/project/customers/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from project import db, app
from markupsafe import escape
import re


# Customer model
Expand All @@ -10,10 +12,24 @@ class Customer(db.Model):
age = db.Column(db.Integer)

def __init__(self, name, city, age):
self.name = name
self.city = city
# na potrzeby weryfikacji w zadaniu funkcja escape jest używana tylko wtedy gdy wykryte są specjalne znaki
if self.contains_special_chars(name):
self.name = escape(name)
else:
self.name = name

if self.contains_special_chars(city):
self.city = escape(city)
else:
self.city = city
self.age = age

@staticmethod
def contains_special_chars(value: str) -> bool:
"""
Sprawdzenie, czy w stringu są znaki specjalne sugerujące wstrzyknięcie.
"""
return bool(re.search(r"[<>&\"'/-;]", value))
def __repr__(self):
return f"Customer(ID: {self.id}, Name: {self.name}, City: {self.city}, Age: {self.age})"

Expand Down
22 changes: 19 additions & 3 deletions Python/Flask_Book_Library/project/loans/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from project import db , app

from markupsafe import escape
import re

# Loan model
class Loan(db.Model):
Expand All @@ -15,14 +16,29 @@ class Loan(db.Model):
original_book_type = db.Column(db.String(64), nullable=False)

def __init__(self, customer_name, book_name, loan_date, return_date, original_author, original_year_published, original_book_type):
self.customer_name = customer_name
self.book_name = book_name
# na potrzeby weryfikacji w zadaniu funkcja escape jest używana tylko wtedy gdy wykryte są specjalne znaki
if self.contains_special_chars(customer_name):
self.customer_name = escape(customer_name)
else:
self.customer_name = customer_name

if self.contains_special_chars(book_name):
self.book_name = escape(book_name)
else:
self.book_name = book_name
self.loan_date = loan_date
self.return_date = return_date
self.original_author = original_author
self.original_year_published = original_year_published
self.original_book_type = original_book_type

@staticmethod
def contains_special_chars(value: str) -> bool:
"""
Sprawdzenie, czy w stringu są znaki specjalne sugerujące wstrzyknięcie.
"""
return bool(re.search(r"[<>&\"'/-;]", value))

def __repr__(self):
return f"Customer: {self.customer_name}, Book: {self.book_name}, Loan Date: {self.loan_date}, Return Date: {self.return_date}"

Expand Down
Binary file added ddd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.