Projekt konceptualny
Celem projektu jest stworzenie modułu do aplikacji internetowej służącej i usprawniającej proces obsługi Ośrodka Szkolenia Kierowców. Wspomniana platforma ma umożliwiać zarządzającym szkołą, instruktorom i kursantom nauki jazdy wygodny dostęp do narzędzi pozwalających i ułatwiających efektywne zarządzanie ośrodkiem szkolenia kierowców oraz kursami, w których uczestniczą klienci
Moduł, który zostanie dodany do aplikacji, będzie umożliwiał zaznaczanie na mapie danego miasta miejsc ciekawych pod względem komunikacyjnym, a więc szczególnie przydatnych w ramach szkolenia początkujących kierowców. Moduł będzie zintegrowany z Google Maps. Instruktorzy i kursanci poprzez kliknięcie w wybranym miejscu mapy będą mogli zaznaczyć interesujące ich miejsce i dodać jego opis.
Analiza stanu wyjściowego
Aktualnie na rynku istnieje niewiele rozwiązań pozwalających na zarządzanie ośrodkiem szkolenia kierowców. Większość rozwiązań dostępnych na rynku nie jest aplikacjami internetowymi i nie umożliwia interakcji z osobami uczestniczącymi w kursach (OSK Manager i Easy OSK). Ich funkcjonalność jest ograniczona do formalnego zarządzania ośrodkiem.
Jedyna dostępna na rynku aplikacja internetowa wspomagająca obsługę ośrodka szkolenia kierowców jest bardziej rozbudowana w stosunku do wspomnianych wyżej aplikacji, jednak jej szata graficzna pozostawia wiele do życzenia i nie jest według nas przystępna.
Najważniejszą rzeczą w przypadku naszego projektu jest to, że żadna z dostępnych na polskim rynku aplikacji nie oferuje modułu, który ma powstać w ramach niniejszego projektu. Kursanci i instruktorzy nie mogą dzielić się informacjami o miejscach komunikacyjnych, które powinien poznać kursant podczas trwania szkolenia. Miejsca takie są niezwykle cenne z dydaktycznego punktu widzenia. Pomocne mogą być także lokalizacje, które często odwiedzają osoby egzaminowane. Zapoznanie z takimi miejscami pozwoli na uzyskanie praktyki i zmniejszenie stresu podczas jazdy egzaminacyjnej.
Analiza wymagań użytkownika (wstępna)
Moduł jest częścią projektu aplikacji do zarządzania ośrodkiem szkolenia kierowców. W aplikacji wyróżniamy kilka rodzajów użytkowników: administratora, instruktora, kursanta, osobę zarządzającą ośrodkiem oraz użytkownika niezalogowanego.
Analiza wymagań odnosić się będzie głównie do tworzonego modułu dodawania nowych miejsc. Nowe miejsca będą mogli dodawać wszyscy zalogowani użytkownicy aplikacji. Jedynym ograniczeniem będzie fakt, że wszystkie miejsca dodane przez kursanta będą podlegać moderacji i będą publikowane dopiero po formalnej akceptacji przez instruktora.
Do podstawowych funkcjonalności projektowanego modułu będą należeć:
Miejsca
Opis miejsca
Komentarz określający, dlaczego miejsce jest warte uwagi (np. trudność, wyjątkowy układ dróg, znaków itp.)
Kategoria
Usuwanie miejsca
Edycja miejsca
Komentarze dotyczące danego miejsca
Kategorie
Wyszukiwanie
Wg kategorii miejsca
Wg oceny
Wg nazwy
Moderowanie dodanych miejsc
Ponadto cała aplikacja internetowa umożliwia w kontekście projektowanego modułu udostępnia:
Określenie scenariuszy użycia
Rejestracja
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Udziałowcy i ich cele:
Gość chce zarejestrować się w systemie
Zdarzenie wyzwalające:
Użytkownik wybiera na stronie opcję rejestracja
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się poprawnie zarejestrować i potwierdzić wybrany adres poczty elektronicznej
Warunki końcowe dla niepowodzenia:
Użytkownik nie zostanie zarejestrowany, użytkownik nie potwierdzi rejestracji, wyświetlony zostanie odpowiedni komunikat.
Scenariusz główny:
System wyświetla formularz logowania
Użytkownik uzupełnia wszystkie wymagane dane
System sprawdza, czy wprowadzone dane są poprawne oraz czy podane login i e-mail są unikatowe
System rejestruje użytkownika i wysyła pocztą elektroniczną e-mail z linkiem aktywacyjnym
Dane użytkownika zostają zapisane w bazie danych
Użytkownik klika w link aktywacyjny
Status użytkownika w bazie danych zostaje zmieniony na „aktywny”
Scenariusze alternatywne
System wyświetla komunikat, które dane są nieprawidłowe i prosi o ich zmianę
Użytkownik wprowadza dane ponownie
Użytkownik nie wprowadza ponownie danych, przypadek użycia kończy się
Powrót do punktu 2 scenariusza głównego
3.2. Podany adres e-mail lub login znajdują się już w bazie użytkowników
System wyświetla komunikat, że podany login lub e-mail są już zajęte
Użytkownik wprowadza nowe dane
Użytkownik nie wprowadza ponownie danych, przypadek użycia kończy się
Powrót do punktu 2 scenariusza głównego
3.3. Użytkownik nie potwierdza rejestracji poprzez kliknięcie w link aktywacyjny w ciągu 24 godzin od próby zarejestrowania się
System usuwa dane użytkownika zapisane w bazie, przypadek użycia kończy się
Logowanie
Aktorzy:
Instruktor
Administrator
Pracownik
Kursant
Zakres:
Platforma do zarządzania OSK
Poziom:
Udziałowcy i ich cele:
Użytkownik chce zalogować się do systemu
Zdarzenie wyzwalające:
Użytkownik wybiera na stronie opcję logowanie
Warunki wstępne:
Użytkownik musi posiadać konto w systemie
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się poprawnie zalogować do systemu
Warunki końcowe dla niepowodzenia:
Użytkownik nie zostanie zalogowany do system, zostanie powiadomiony o braku zalogowania (niepoprawne dane).
Scenariusz główny:
System wyświetla okno logowania
Użytkownik uzupełnia login i hasło
System sprawdza, czy dane są poprawne
System loguje użytkownika do aplikacji
Scenariusze alternatywne:
3.1. Wpisano niepoprawne dane
System wyświetla komunikat, że dane są nieprawidłowe i umożliwia wprowadzenie danych ponownie
Użytkownik wprowadza dane ponownie
Użytkownik nie wprowadza ponownie danych
System powraca do okna logowanie, przypadek użycia kończy się
Powrót do punktu 2 scenariusza głównego
Dodawanie miejsca
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map - dodanie nowego miejsca
Udziałowcy i ich cele:
Użytkownik chce dodać nowe miejsce na mapie
Zdarzenie wyzwalające:
Użytkownik klika na mapie współrzędne danego miejsca
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się poprawnie dodać miejsce (w przypadku kursanta miejsce może oczekiwać na akceptację)
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie uda się dodać nowego miejsca.
Scenariusz główny:
Użytkownik klika na wybranym miejscu na mapie
Użytkownik uzupełnia dane potrzebne do zapisania miejsca (opis, komentarz, kategoria)
System sprawdza, czy wprowadzone dane są poprawne
System zapisuje miejsce w bazie danych
Scenariusze alternatywne:
2.2. Użytkownik chce dodać nową kategorię
Użytkownik klika w przycisk umożliwiający dodanie nowej kategorii
Użytkownik wprowadza dane dotyczące kategorii (nazwa)
Jeżeli dane są niepoprawne system nie dodaje nowej kategorii i powraca do punktu 3 scenariusza głównego
System sprawdza dane
Jeżeli dane są poprawne system zapisuje kategorię, system wraca do punktu 4 scenariusza głównego
3.1. Wpisano niepoprawne dane
System wyświetla komunikat, że dane są nieprawidłowe i umożliwia wprowadzenie danych ponownie
Użytkownik wprowadza dane ponownie
Użytkownik nie wprowadza ponownie danych
System powraca do okna logowanie, przypadek użycia kończy się
Powrót do punktu 5 scenariusza głównego
4.1. Użytkownik dodający miejsce jest kursantem
Miejsce dodane przez kursanta trafia na listę miejsc do moderacji
Instruktor potwierdza lub odrzuca miejsce, przypadek użycia kończy się
Edytowanie miejsca
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – edycja miejsca
Udziałowcy i ich cele:
Użytkownik chce zmienić dane dotyczące zapisanego miejsca
Zdarzenie wyzwalające:
Użytkownik klika na mapie współrzędne danego miejsca (marker)
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się edycja danych dotyczących miejsca
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie uda się zmienić informacji o danym miejscu
Scenariusz główny
Użytkownik klika na zaznaczonym miejscu na mapie (oznaczenie kolorowym markerem)
Użytkownik wybiera opcję „Edytuj”
System wyświetla formularz z danymi do edycji
Użytkownik edytuje dane i wybiera opcję zapisu
System sprawdza, czy wprowadzone dane są poprawne
System zapisuje dane po edycji
Scenariusze alternatywne:
5.1. Wpisano niepoprawne dane
System wyświetla komunikat, że dane są nieprawidłowe i umożliwia edycję danych ponownie
Użytkownik edytuje dane ponownie
Użytkownik nie wprowadza ponownie danych
System powraca do okna głównego modułu, przypadek użycia kończy się
Powrót do punktu 5 scenariusza głównego
Usuwanie miejsca
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – usuwanie miejsca
Udziałowcy i ich cele:
Użytkownik chce usunąć zapisane miejsce
Zdarzenie wyzwalające:
Użytkownik klika na mapie współrzędne danego miejsca (marker)
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje usunąć wybrane miejsce
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie udaje się usunąć danego miejsca
Scenariusz główny:
Użytkownik klika na zaznaczonym miejscu na mapie (oznaczenie kolorowym markerem)
Użytkownik wybiera opcję „Usuń”
System wyświetla prośbę o potwierdzenie chęci usunięcia miejsca
Użytkownik potwierdza chęć usunięcia
Miejsce zostaje usunięte
Scenariusze alternatywne:
4.1. Użytkownik nie potwierdza chęci usunięcia miejsca
System wyświetla komunikat, że miejsce nie zostało usunięte, przypadek użycia kończy się
Dodanie komentarza na temat miejsca
Aktorzy:
Instruktor
Administrator
Pracownik
Kursant
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – komentarz danego miejsca
Udziałowcy i ich cele:
Użytkownik chce dodać komentarz, opinię na temat danego miejsca
Zdarzenie wyzwalające:
Użytkownik klika na mapie współrzędne danego miejsca (marker)
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się dodać komentarz
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie udaje się dodać komentarza
Scenariusz główny:
Użytkownik klika na zaznaczonym miejscu na mapie (oznaczenie kolorowym markerem)
Użytkownik wybiera opcję „Dodaj komentarz”
System wyświetla formularz do wpisania komentarza
System sprawdza dane wpisane w komentarzu
Komentarz do danego miejsca zostaje zapisany
Scenariusze alternatywne:
4.1. Wpisano niepoprawne dane
System wyświetla komunikat, że dane są nieprawidłowe i umożliwia wprowadzenie danych ponownie
Użytkownik wprowadza dane ponownie
Użytkownik nie wprowadza ponownie danych
System powraca do okna logowanie, przypadek użycia kończy się
Powrót do punktu 4 scenariusza głównego
Dodanie kategorii
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – dodanie kategorii
Udziałowcy i ich cele:
Użytkownik chce dodać nową kategorię
Zdarzenie wyzwalające:
Użytkownik wybiera odnośnik „dodaj nową kategorię”
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się dodać kategorię
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie udaje się dodać kategorii
Scenariusz główny:
System wyświetla formularz dodania kategorii
Użytkownik wpisuje dane
System sprawdza dane wpisane w formularzu
Kategoria zostaje dodana
Scenariusze alternatywne:
3.1. Wpisano niepoprawne dane
System wyświetla komunikat, że dane są nieprawidłowe i umożliwia wprowadzenie danych ponownie
Użytkownik wprowadza dane ponownie
Użytkownik nie wprowadza ponownie danych
System powraca do okna logowanie, przypadek użycia kończy się
Powrót do punktu 3 scenariusza głównego
Usuwanie kategorii
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – usuwanie kategorii
Udziałowcy i ich cele:
Użytkownik chce usunąć kategorię
Zdarzenie wyzwalające:
Użytkownik wybiera odnośnik „usuń kategorię”
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się usunąć kategorię
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie udaje się usunąć kategorii
Scenariusz główny:
System wyświetla dostępne kategorie
Użytkownik wybiera kategorię i odnośnik „usuń”
System wyświetla komunikat z prośbą o potwierdzenie chęci usunięcia kategorii
Użytkownik potwierdza usunięcie
Kategoria zostaje usunięta
Scenariusze alternatywne:
4.1. Użytkownik nie potwierdza chęci usunięcia miejsca
System wyświetla komunikat, że miejsce nie zostało usunięte, przypadek użycia kończy się
Wyszukiwanie miejsc
Aktorzy:
Instruktor
Administrator
Pracownik
Kursant
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – wyszukiwanie miejsc
Udziałowcy i ich cele:
Użytkownik chce odnaleźć miejsce
Zdarzenie wyzwalające:
Użytkownik wybiera odnośnik „wyszukaj miejsce”
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się odnaleźć miejsce
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie udaje się odnaleźć miejsca
Scenariusz główny:
System wyświetla formularz wyszukiwania wraz z możliwymi filtrami
Użytkownik wybiera filtr i wpisuje ciąg do wyszukania
System szuka miejsca w bazie danych
System wyświetla rezultat wyszukiwania
Moderowanie nowych miejsc
Aktorzy:
Zakres:
Platforma do zarządzania OSK
Poziom:
Moduł map – moderowanie miejsc
Udziałowcy i ich cele:
Instruktor chce ocenić i ewentualnie dodać miejsca wprowadzone przez kursantów
Zdarzenie wyzwalające:
Użytkownik wybiera odnośnik „moderuj dodane miejsca”
Warunki wstępne:
Użytkownik musi posiadać konto w systemie i być zalogowanym
Warunki końcowe dla sukcesu:
Użytkownikowi udaje się dokonać moderacji danego miejsca
Warunki końcowe dla niepowodzenia:
Użytkownikowi nie udaje się dokonać moderacji danego miejsca
Scenariusz główny:
System wyświetla listę miejsc do moderacji
Instruktor wybiera miejsce i ocenia jego przydatność
Instruktor akceptuje dane miejsce
Miejsce zostaje dodane do bazy i jest wyświetlane na mapie
Scenariusze alternatywne:
3.1. Instruktor nie akceptuje danego miejsca
System wyświetla komunikat, że miejsce zostało usunięte, przypadek użycia kończy się
Baza danych ma realizować następujące funkcje
Rejestracja i logowanie, wylogowanie
Przechowywanie i udostępnianie informacji o miejscach ciekawych pod względem komunikacyjnym
Wyszukiwanie miejsc
Dodawanie / usuwanie nowych miejsc
Dodawanie komentarzy
Moderowanie dodanych miejsc
Kategoryzacja miejsc
Analiza hierarchii funkcji projektowanej aplikacji
Budowa i analiza diagramu przepływu danych
Diagram kontekstowy
Diagram wstępny
1. Obsługa konta
2. Obsługa miejsc
3. Obsługa kategorii
Diagram związków encji (ERD)
Projekt logiczny
Doprecyzowanie struktury bazy
Schemat
Kod SQL
CREATE TABLE address (
id integer NOT NULL,
street VARCHAR(64),
house_number VARCHAR(10) NOT NULL,
flat_number VARCHAR(10),
town VARCHAR(64) NOT NULL,
postal_code VARCHAR(6) NOT NULL,
post_office varchar(64) not null
);
ALTER TABLE address ADD CONSTRAINT address_pk PRIMARY KEY (id);
CREATE TABLE users (
id integer NOT NULL,
username VARCHAR(32) not null,
pass_sha256 char(64) not null,
pass_salt char(64) not null,
code_sha256 char(64),
email varchar(128) not null,
phone varchar(16),
mobile varchar(16),
status integer not null,
first_name VARCHAR(64),
last_name VARCHAR(64),
pesel char(11),
birth_date DATE,
nationality VARCHAR(64),
home_address integer not null,
mailing_address integer,
register_date timestamp,
last_login_date timestamp
);
ALTER TABLE users ADD CONSTRAINT users_pk PRIMARY KEY (id);
ALTER TABLE users ADD CONSTRAINT users_home_address_fk FOREIGN KEY (home_address)
REFERENCES address (id);
ALTER TABLE users ADD CONSTRAINT users_mailing_address_fk FOREIGN KEY (mailing_address)
REFERENCES address (id);
CREATE TABLE "payments_status" (
"id" integer NOT NULL,
"description" varchar(200) NOT NULL
);
ALTER TABLE "payments_status" ADD CONSTRAINT "payments_status_pk" PRIMARY KEY ("id");
CREATE TABLE "students" (
"user_id" integer NOT NULL
);
ALTER TABLE "students" ADD CONSTRAINT "students_pk" PRIMARY KEY ("user_id");
ALTER TABLE "students" ADD CONSTRAINT "students_user_id_fk" FOREIGN KEY ("user_id")
REFERENCES "users" ("id");
CREATE TABLE "payments" (
"id" integer NOT NULL,
"amount" numeric(9,2) NOT NULL,
"date" date NOT NULL,
"student_id" integer NOT NULL,
"accepted_by" integer NOT NULL,
"status" integer NOT NULL,
"due_date" date,
"description" integer
);
ALTER TABLE "payments" ADD CONSTRAINT "payments_pk" PRIMARY KEY ("id");
ALTER TABLE "payments" ADD CONSTRAINT "payments_student_id_fk" FOREIGN KEY ("student_id")
REFERENCES "student" ("user_id");
ALTER TABLE "payments" ADD CONSTRAINT "payments_status_fk" FOREIGN KEY ("status")
REFERENCES "payments_status" ("id");
CREATE TABLE "categories" (
"category_code" varchar(4) NOT NULL,
"category_name" varchar NOT NULL
);
ALTER TABLE "categories" ADD CONSTRAINT "categories_pk" PRIMARY KEY ("category_code");
CREATE TABLE "student_categories" (
"student_id" integer NOT NULL,
"category_code" varchar(4) NOT NULL
);
ALTER TABLE "student_categories" ADD CONSTRAINT "student_categories_pk" PRIMARY KEY ("student_id","category_code");
ALTER TABLE "student_categories" ADD CONSTRAINT "student_categories_student_id_fk" FOREIGN KEY ("student_id")
REFERENCES "students" ("user_id");
ALTER TABLE "student_categories" ADD CONSTRAINT "student_categories_category_code_fk" FOREIGN KEY ("category_code")
REFERENCES "categories" ("category_code");
CREATE TABLE "courses" (
"id" integer NOT NULL,
"start_date" date NOT NULL,
"type" varchar(3) NOT NULL,
"practical_training" integer NOT NULL,
"theoretical_training" integer NOT NULL
);
ALTER TABLE "courses" ADD CONSTRAINT "courses_pk" PRIMARY KEY ("id");
CREATE TABLE "cars" (
"id" integer NOT NULL,
"registration_number" varchar(7) NOT NULL,
"brand" varchar(50) NOT NULL,
"model" varchar(50) NOT NULL,
"colour" varchar(50) NOT NULL,
"year" integer NOT NULL,
"examination_date" date,
"insurance_date" date,
"category" varchar(4),
"disctance" integer
);
ALTER TABLE "cars" ADD CONSTRAINT "cars_pk" PRIMARY KEY ("id");
ALTER TABLE "cars" ADD CONSTRAINT "cars_category_fk" FOREIGN KEY ("category")
REFERENCES "categories" ("category_code");
CREATE TABLE "student_courses" (
"course_id" integer NOT NULL,
"student_id" integer NOT NULL,
"medical_certificate" bool,
"instructor" integer,
"certificate_number" varchar(10),
"end_date" date
);
ALTER TABLE "student_courses" ADD CONSTRAINT "student_courses_pk" PRIMARY KEY ("course_id","student_id");
ALTER TABLE "student_courses" ADD CONSTRAINT "student_courses_course_id_fk" FOREIGN KEY ("course_id")
REFERENCES "courses" ("id");
ALTER TABLE "student_courses" ADD CONSTRAINT "student_courses_student_id_fk" FOREIGN KEY ("student_id")
REFERENCES "students" ("user_id");
ALTER TABLE "student_courses" ADD CONSTRAINT "student_courses_instructor_fk" FOREIGN KEY ("instructor")
REFERENCES "instructors" ("user_id");
CREATE TABLE "internal_exams" (
"id" integer NOT NULL,
"student_id" integer NOT NULL,
"course_id" integer NOT NULL,
"type" char(1) NOT NULL,
"result" bool NOT NULL DEFAULT False,
"date" date NOT NULL,
"instructor" integer NOT NULL,
"errors" varchar(500)
);
ALTER TABLE "internal_exams" ADD CONSTRAINT "internal_exams_pk" PRIMARY KEY("id","student_id","course_id");
ALTER TABLE "internal_exams" ADD CONSTRAINT "internal_exams_student_course_id_fk" FOREIGN KEY ("student_id", "course_id")
REFERENCES "student_courses"("student_id", "course_id");
ALTER TABLE "internal_exams" ADD CONSTRAINT "internal_exams_instructor_fk" FOREIGN KEY ("instructor")
REFERENCES "instructors" ("user_id");
CREATE TABLE "status" (
"id" integer NOT NULL,
"name" varchar(100)
);
ALTER TABLE "status" ADD CONSTRAINT "status_pk" PRIMARY KEY("id");
CREATE TABLE "driving_lessons" (
"id" integer NOT NULL,
"student_id" integer NOT NULL,
"instructor_id" integer NOT NULL,
"start_time" timestamp NOT NULL,
"end_time" timestamp NOT NULL,
"course_id" integer NOT NULL,
"status" integer NOT NULL,
"distance" integer,
"car_id" integer NOT NULL
);
ALTER TABLE "driving_lessons" ADD CONSTRAINT "driving_lessons_pk" PRIMARY KEY("id");
ALTER TABLE "driving_lessons" ADD CONSTRAINT "driving_lessons_student_id_fk" FOREIGN KEY ("student_id")
REFERENCES "students" ("user_id");
ALTER TABLE "driving_lessons" ADD CONSTRAINT "driving_lessons_instructor_id_fk" FOREIGN KEY ("instructor_id")
REFERENCES "instructors" ("user_id");
ALTER TABLE "driving_lessons" ADD CONSTRAINT "driving_lessons_course_id_fk" FOREIGN KEY ("course_id")
REFERENCES "courses" ("id");
ALTER TABLE "driving_lessons" ADD CONSTRAINT "driving_lessons_status_fk" FOREIGN KEY ("status")
REFERENCES "status" ("id");
ALTER TABLE "driving_lessons" ADD CONSTRAINT "driving_lessons_car_id_fk" FOREIGN KEY ("car_id")
REFERENCES "cars" ("id");
CREATE TABLE "theoretical_lessons" (
"id" integer NOT NULL,
"course_id" integer,
"instuctor_id" integer,
"subject" varchar(200),
"date" timestamp NOT NULL,
"hours" integer NOT NULL,
"class" varchar(5)
);
ALTER TABLE "theoretical_lessons" ADD CONSTRAINT "theoretical_lessons_pk" PRIMARY KEY("id");
ALTER TABLE "theoretical_lessons" ADD CONSTRAINT "theoretical_lessons_course_id_fk" FOREIGN KEY ("course_id")
REFERENCES "courses" ("id");
ALTER TABLE "theoretical_lessons" ADD CONSTRAINT "theoretical_lessons_instructor_id_fk" FOREIGN KEY ("instuctor_id")
REFERENCES "instructors" ("user_id");
CREATE TABLE "comments" (
"id" integer NOT NULL,
"place_id" integer,
"comment" varchar(1024) NOT NULL,
"author" integer,
"date" date,
"grade" integer
);
ALTER TABLE comments ADD CONSTRAINT comments_pk PRIMARY KEY (id);
CREATE TABLE "interesting_places" (
"id" integer NOT NULL,
"lattitude" float8 NOT NULL,
"longitude" float8 NOT NULL,
"type_id" integer,
"description" varchar(512),
"accepted" bool NOT NULL,
"city" varchar(32) NOT NULL,
"author" varchar(32) NOT NULL,
"date" date NOT NULL
);
ALTER TABLE interesting_places ADD CONSTRAINT interesting_places_pk PRIMARY KEY (id);
CREATE TABLE "types" (
"id" integer NOT NULL,
"name" varchar(256) NOT NULL,
"description" varchar(1024),
PRIMARY KEY("id")
);
ALTER TABLE "types" ADD CONSTRAINT types_pk PRIMARY KEY (id);
ALTER TABLE "comments" ADD CONSTRAINT "comments_users_fk" FOREIGN KEY ("author") REFERENCES "users"("id")
ALTER TABLE "comments" ADD CONSTRAINT "comments_interesting_places_fk" FOREIGN KEY ("place_id") REFERENCES "interesting_places"("id") on delete cascade
ALTER TABLE "interesting_places" ADD CONSTRAINT "interesting_places_types_fk" FOREIGN KEY ("type_id") REFERENCES "types"("id") on delete cascade
ALTER TABLE "interesting_places" ADD CONSTRAINT "interesting_places_users_fk" FOREIGN KEY ("author") REFERENCES "users"("id") on delete cascade
Słowniki danych
address - tabela przechowująca adresy stałe i korespondencyjne użytkowników
id - id adresu, klucz główny, INTEGER, NOT NULL
street - nazwa ulicy - VARCHAR(64)
house_number - nr domu, VARCHAR(10) NOT NULL
flat_number - nr mieszkania, VARCHAR(10)
town - nazwa miasta, VARCHAR(64) NOT NULL
postal_code - kod pocztowy, VARCHAR(6) NOT NULL
post_office - nazwa poczty, VARCHAR(64), NOT NULL
cars - tabela przechowująca dane o pojazdach szkoleniowych
id - id pojazdu, klucz główny, INTEGER, NOT NULL
registration_number - nr rejestracyjny, VARCHAR(7) NOT NULL,
brand - marka pojazdu, VARCHAR(50) NOT NULL
model - model pojazdu, VARCHAR(50) NOT NULL
colour - kolor pojazdu, VARCHAR(50) NOT NULL
year - rok produkcji, INTEGER, NOT NULL
examination_date - data następnego badania technicznego, DATE
insurance_date - data ważności ubezpieczenia OC, DATE
category - klucz obcy do tabeli CATEGORIES (category_code) kategoria nauki jazdy, dla której pojazd jest przeznaczony, VARCHAR(4)
distance - przebieg, INTEGER
categories - tabela przechowująca kategorie praw jazdy
category_code - klucz główny, kod kategorii prawa jazdy np. B+E, VARCHAR(4), NOT NULL
category_name - nazwa kategorii, VARCHAR(20), NOT NULL
courses - tabela przechowująca informacje o kursach
id - klucz główny, id kursu, INTEGER, NOT NULL
start_date - data rozpoczęcia kursu, DATE, NOT NULL
type - typ kursu (podstawowy - P, dodatkowy - D itp), VARCHAR(3), NOT NULL
practical_training - liczba godzin szkolenia praktycznego, INTEGER, NOT NULL
theoretical_training - liczba godzin szkolenia teoretycznego, INTEGER, NOT NULL
driving_lessons - tabela przechowująca informacje o jazdach kursanta (zajęcia praktyczne)
id - klucz główny, nr zajęcia praktycznego (jazdy), INTEGER, NOT NULL
student_id - nr id studenta, klucz obcy do tabeli STUDENTS (user_id), INTEGER, NOT NULL
instructor_id - nr id instruktora, klucz obcy do tabeli INSTRUCTORS (user_id), INTEGER, NOT NULL
start_time - data i godzina rozpoczęcia, TIMESTAMP
end_time - data i godzina zakończenia, TIMESTAMP
course_id - kurs, którego dotyczą zajęcia, klucz obcy do tabeli COURSES (ID), INTEGER, NOT NULL
status - status zajęć, klucz obcy do tabeli STATUS (ID), INTEGER, NOT NULL
distance - ilość przebytych km, INTEGER
car_id - nr id pojazdu do nauki jazdy, klucz obcy do tabeli CARS (ID), INTEGER, NOT NULL
employees - tabela przechowująca informacje o pracownikach nie będących instruktorami
id - nr id pracownika, klucz główny, NOT NULL, INTEGER
nip - nr NIP pracownika, VARCHAR(12), NOT NULL
account_number - nr konta bankowego, CHAR(26)
instructors tabela przechowująca informacje o instruktorach
user_id - nr id instruktora, klucz główny, INTEGER, NOT NULL
account_number - nr konta bankowego, CHAR(26)
internal_exams - tabela przechowująca informacje o egzaminach wewnętrznych
id - nr id egzaminu wewnętrznego, klucz główny, NOT NULL, INTEGER
student_id - id studenta, klucz obcy złożony („student_id”, „course_id”) do tabeli STUDENTS_COURSES (STUDENT_ID, COURSE_ID), INTEGER, NOT NULL
course_id - id kursu, klucz obcy złożony („student_id”, „course_id”) do tabeli STUDENTS_COURSES (STUDENT_ID, COURSE_ID), INTEGER, NOT NULL
type - typ egzaminu (pisemny, praktyczny), CHAR(1), NOT NULL
result - wynik, BOOL, NOT NULL
date - data, DATE, NOT NULL
instructor - nr id instruktora przeprowadzającego egzamin, klucz obcy do tabeli INSTRUCTORS (USER_ID), NOT NULL, INTEGER
errors - opis błędów, VARCHAR(500)
payments - tabela przechowująca informacje o płatnościach
id - nr id płatności, klucz główny, INTEGER, NOT NULL
amount - kwota, NUMERIC(9,2), NOT NULL
date - data płatności, NOT NULL
student_id - id studenta, klucz obcy do tabeli STUDENTS (USER_ID), INTEGER, NOT NULL
accepted_by - nr id osoby akceptującej płatność, INTEGER, NOT NULL
status - nr id statusu płatności, klucz obcy do tabeli PAYMENTS_STATUS (ID), INTEGER, NOT NULL
due_date - data ważności, DATE
description - opis, VARCHAR(200)
payments_status - tabela przechowująca statusy płatności
id - nr id statusu płatności, klucz główny, INTEGER, NOT NULL
description - opis statusu płatności, VARCHAR(200), NOT NULL
status - statusy zajęć praktycznych (zarezerwowane, odbyte itp.)
id - nr id statusu, klucz główny, INTEGER, NOT NULL
name - nazwa statusu, VARCHAR(100), NOT NULL
student_categories - tabela odwzorowująca relację wiele do wielu (student-kategoria)
student_id - nr id studenta, klucz główny, klucz obcy do tabeli STUDENTS (USER_ID), INTEGER, NOT NULL
category_code - kod kategorii, klucz główny, klucz obcy do tabeli CATEGORIES (CATEGORY_CODE), VARCHAR(4), NOT NULL
student_courses - tabela odwzorowująca relację wiele do wielu (student-kurs) i przechowująca informacje dotyczące konkrestnego studenta i kursu
course_id - nr id kursu, klucz główny, INTEGER, NOT NULL
student_id - nr id studenta, klucz główny, INTEGER, NOT NULL
medical_certificate - określenie posiadania zaświadczenia lekarskiego, BOOL
instructor - nr id instruktora, klucz obcy do tabeli INSTRUCTORS (USER_ID), INTEGER
certificate_number - nr zaświadczenia lekarskiego, VARCHAR(10)
end_date - data zakończenia, DATE
students - tabela przechowująca studentów
user_id - nr id studenta, klucz główny, klucz obcy do tabeli USERS (ID), INTEGER, NOT NULL
theoretical_lessons - tabela z danymi na temat zajęć teoretycznych
id - nr id zajęć teoretycznych, klucz główny, INTEGER, NOT NULL
course_id - id kursu, klucz obcy do tabeli COUSRES (ID), INTEGER, NOT NULL
instructor_id - id instruktora, klucz obcy do tabeli INSTRUCTORS (USER_ID)
subject - tematyka, VARCHAR(200)
date - data, TIMESTAMP, NOT NULL
hours - czas trwania w godz., INTEGER, NOT NULL
class - sala, VARCHAR(5)
users - tabela przechowująca dane o użytkownikach aplikacji
id - klucz główny, INTEGER, NOT NULL
username - nazwa użytkownika, username VARCHAR(32) NOT NULL
pass_sha256 - zaszyfrowane hasło, char(64), NOT NULL
pass_salt - sól, CHAR(64), NOT NULL
code_sha256 - CHAR(64)
email - adres e-mail użytkownika, VARCHAR(128), NOT NULL
phone - nr telefonu, VARCHAR(16)
mobile - nr telefonu komórkowego, VARCHAR(16)
status - status użytkownika, odniesienie do tabeli status (ID), INTEGER, NOT NULL
first_name - imię, VARCHAR(64)
last_name - nazwisko, VARCHAR(64)
pesel - nr pesel, CHAR(11)
birth_date - data urodzenia, DATE
nationality - narodowość, VARCHAR(64)
home_address - odniesienie do tabeli adress (pole ID), INTEGER, NOT NULL
mailing_address - odniesienie do tabeli adress (pole ID), INTEGER
register_date - data rejestracji, TIMESTAMP
last_login_date - data ostatniego logowania, TIMESTAMP
comments - tabela przechowujaca komentarze użytkowników dotyczące miejsc
id - nr id komentarza, klucz główny, INTEGER, NOT NULL
place_id - id miejsca, klucz obcy do tabeli INTERESTING_PLACES (ID), INTEGER, NOT NULL
comment - treść komentarza, VARCHAR(1024), NOT NULL
author - autro komentarza (jego id), klucz obcy do tabeli USERS (ID), INTEGER
date - data, TIMESTAMP
grade - ocena miejsca, INTEGER
interesting_places - tabela przechowujaca dane dotyczące ciekawych miejsc
id - nr id miejsca, klucz główny, INTEGER, NOT NULL
lattitude - szerokość geograficzna, FLOAT, NOT NULL
longitude - długość geograficzna, FLOAT, NOT NULL
type_id - id typu miejsca, klucz obcy do tabeli TYPES (ID), INTEGER`
description - opis miejsca, VARCHAR(512)
accepted - zmienna określająca, czy miejsce zostało poddane moderacji i zaakceptowane, BOOL, NOT NULL
city - miasto, w którym jest dane miejsce, VARCHAR(32), NOT NULL
author - użytkownik, który dodał miejsce, INTEGER, NOT NULL
date - data dodania, DATE, NOT NULL
types - tabela przechowujaca typy ciekawych miejsc
id - nr id typu, klucz główny, INTEGER, NOT NULL
name - nazwa typu, VARCHAR(256), NOT NULL
longitude - długość geograficzna, FLOAT, NOT NULL
description - opis typu, VARCHAR(1024)
Analiza zależności funkcyjnych i normalizacja tabel
Pierwsza postać normalna - 1NF
Wszystkie atrybuty spełniają warunek atomiczności, czyli pierwsza postać normalna jest zachowana.
Druga postać normalna - 2NF
Baza jest w pierwszej postaci normalnej i każdy atrybut niekluczowy relacji jest w pełni funkcjonalnie zależny od wszystkich kluczy niezależnych.
Trzecia postać normalna - 3NF
Baza jest w drugiej postaci normalnej oraz brak jest w niej przechodnich zależności funkcjonalnych. Spełnia więc warunki 3NF.
Projektowanie operacji na danych
Poniżej przedstawiono przykładowe instrukcje SQL realizujące funkcjonalności systemu.
1. Rejestracja kursanta:
insert into address (id, street_number, street, house_number, city, postcode, phone, mobile, email) values(1, '12b', 'Akacjowa', '39C', 'Kraków', '30-031', null, '503323332', 'mail@gmail.com');
insert into users (id, username, pass_sha256, pass_salt, code_sha256, status, first_name, last_name, pesel, birth_date, nationality, home_address, mailing_address) values(1, 'login', 'fdf9136b1e83481e68f9d94deba79539dd4aee8df5e6d5cb8e38466d24b9d89e', 'LIkQyqduKEkKsTCaZAqIFN4gwQtorxzKyXbi24GaBsLUOr6NgDwSGWFozhpS2aLo', '40d6ab39842f7fa95a7c71a528d0885a7ee9b9534d0bd3c2c380fc098d55b25f', 1, 'imie', 'nazwisko', '82031209214', '1982-03-12', 'polskie', 1, null);
insert into students (id) values(1);
2. Dodawanie kategorii:
insert into types(id, name, description) values (1, 'Ronda', 'Ronda, na których kursanci najczęściej popełniają błędy');
2. Dodawanie miejsca (przez kursanta):
insert into interesting_places(id, latitude, longitude, type_id, description, accepted, city, author, date) values (421, 50.05, 19.95, 1, 'Rondo grzegórzeckie - tutaj najczęściej...', false, 'Kraków', 1, current_date);
3. Akceptacja miejsca przez moderatora:
update interesting_places set accepted = 'true' where id = 423;
4. Edycja danych miejsca (współrzędne i opis):
update interesting_places set latitude = 20.33, longitude = 55.64, description = 'nowy, lepszy opis' where id = 423;
5. Usuwanie miejsca:
delete from interesting_places where id = 4224;
6. Dodanie komentarza na temat miejsca:
insert into comments(id, place_id, comment, author, date, grade) values (23, 523, 'Tutaj oblałem egzamin', 4, current_date, 5);
7. Usuwanie miejsca:
delete from interesting_places where id = 423; -- relacje są typu on delete cascade, komentarze do miejsca również się usuną
8. Usuwanie kategorii:
delete from types where id = 123; -- relacje są typu on delete cascade, więc wszystkie miejsca kategorii również się usuną (wraz z komentarzami)
9. Wyszukiwanie miejsc w pewnym obszarze:
select * from interesting_places where latitude between 50.05 and 52.10 and longitute beetwen 19.95 and 23.10
Projekt końcowy
Implementacja bazy danych
Implementacja bazy danych nastąpiła w oparciu o skrypt SQL przygotowany w ramach części projektowej zadania.
Skrypt SQL
Do stworzenia skryptu wykorzystano przygotowany schemat ERD znajdujący się również w projekcie logicznym modułu aplikacji do zarządzania Ośrodkiem Szkolenia Kierowców.
Schemat
Zdefiniowanie interfejsów do prezentacji, edycji i obsługi danych
Dodawanie nowej kategorii
Dodawanie nowego miejsca
Wyszukaj miejsce na mapie
Zdefiniowanie dokumentów do przetwarzania i prezentacji danych
Projektowany moduł aplikacji dotyczy możliwości zaznaczania na mapie danego miasta ciekawych pod względem komunikacyjnym miejsc i ich komentowania oraz oceniania. Z tego względu moduł nie będzie posiadał funkcjonalności prezentacji i tworzenia dokumentów oraz raportów, gdyż zakres modułu nie dotyczy bezpośrednio dokumentacji ośrodka szkolenia kierowców.
Istnieje ewentualnie możliwość generowania informacji o dodanych miejscach (wszystkich lub wybranych wg odpowiedniego kryterium) np.:
Wyszukanie wszystkich miejsc:
select * from interesting_places
Wyszukanie miejsc w intersującym nas obszarze:
select * from interesting_places where latitude between 50.05 and 52.10 and longitute beetwen 19.95 and 23.10
Zdefiniowanie panelu sterowania aplikacji
Zdefiniowanie makropoleceń dla realizacji typowych operacji
Uruchamianie i testowanie aplikacji
Aplikacja została stworzona przy wykorzystaniu narzędzia Eclipse w języku Java EE. Baza danych została zaimplementowana na koncie hostingowym umożliwiającym korzystanie z PostgreSQL. Aplikacja uruchamia się poprzez przeglądarkę i jest dostosowana do dwóch popularnych przeglądarek internetowych: Firefox oraz Opera.
Wprowadzanie danych
Dane można wprowadzać za pomocą stworzonych formularzy. Są one narzędziem wystarczającym, jednak w przypadku konieczności wprowadzenia dużej ilości danych, można stworzyć odpowiednie skrypty zapisujące je bezpośrednio do bazy danych.
Wdrażanie systemu do użytkowania
Wdrożenie będzie obejmować następujące czynności:
skonfigurowanie serwera aplikacji JBossAS w wersji 6
uruchomienie serwera bazy danych PostgreSQL oraz stworzenie odpowiednich jej struktur
deploy aplikacji na serwerze i uruchomienie serwera
Przeprowadzenie szkolenia użytkowników
Klientowi zostanie dostarczona dokumentacja aplikacji wraz z jej instrukcją obsługi. Aplikacja jest na tyle intuicyjna, że inne rodzaje szkoleń nie będą konieczne.
Zapewnienie obsługiwania systemu po wdrożeniu
System będzie wymagał zatrudnienia administratora obsługującego panel administracyjny, kontrolującego poprawność danych w bazie i zgłaszającego ewentualnie znalezione błędy w działaniu systemu.
Rozwijanie i modyfikowanie aplikacji
Aplikacja będzie poprawiana na podstawie zgłaszanych przez klienta błędów. Jest również możliwe podpisanie nowego kontraktu obejmującego dodanie nowych funkcjonalności na które klient zgłasza zapotrzebowanie.
Opracowanie doświadczeń wynikających z realizacji projektu
Ważnym doświadczeniem wyniesionym z realizacji projektu są podstawy konfigurowania serwera aplikacji JBoss. Poprawne skonfigurowanie go, tak żeby działał wydajnie, stabilnie i zawierał wszystkie potrzebne funkcje jest trudną i wymagającą dużej wiedzy czynnością.
Dowiedzieliśmy się też, że na poprawne zaprojektowanie bazy danych dla tak dużej aplikacji potrzeba dużo czasu i bardzo gruntownego jej przemyślenia. Trzeba rozwiązać problemy związane z jednoznacznością i spójnością danych, szybkością bazy oraz jej rozmiarem.
Z wykorzystaniem bazy danych w aplikacji wiążą się mapowania obiektowo-relacyjne. Do ich realizacji użyliśmy biblioteki Hibernate. Sprawiła nam ona nieco problemów, gdyż ciężko było stworzyć kod który nie pobierałby połowy bazy danych niepotrzebnie. Trudnym do zlokalizowania błędem okazała się nazwa kolumny zawierająca słowo kluczowe języka wykorzystywanego przez Hibernate do komunikacji z serwerem bazodanowym.
Inną istotne umiejętności nabyte podczas pracy nad projektem, to poprawne planowanie czasu potrzebnego na wykonanie projektu, zwłaszcza w sytuacji mocnego obłożenia innymi projektami i wykorzystanie biblioteki RichFaces. Zwłaszcza tą ostatnią poznaliśmy bardzo dokładnie, z uwzględnieniem występujących w niej błędów.