====== Portal społecznościowy GdziePoPiwo?pl (t) ======
[[kruzeltomasz@gmail.com|Tomasz Krużel]],
[[krzysiek861@wp.pl|Krzysztof Lelito]],
[[phobo@gmail.com|Janusz Lisiecki]]
==== Streszczenie ====
Projekt bazy danych wykorzystanej w stronie internetowej http://www.gdziepopiwo.pl.
==== Sformułowanie zadania projektowego ====
Celem projektu jest stworzenie strony internetowej na której będzie można znaleźć najtańsze piwo w okolicy. Nasza strona będzie oparta o rozbudowany system CMS. Użytkownik mógłby w łatwy sposób wyszukać gdzie w jego okolicy można dostać konkretne piwo i w jakiej cenie. Baza cen, asortymentu i sklepów byłaby modyfikowana przez samych zarejestrowanych użytkowników portalu. Integracja z API Google Maps ułatwi lokalizację sklepów.
==== Analiza stanu wyjściowego ====
Jeśli chodzi o polski rynek, to w momencie projektowania, nie było rozwiązania takiego jak nasze. Istnieją jedynie portale dotyczące innych produktów, np. strona dotyczący cen paliwa http://www.dobaku.pl/
adresowana do kierowców gdzie możemy znaleźć najtańszą stację z paliwem w Krakowie. Jedyne rozwiązanie związane z piwem jakie udało nam się znaleźć to http://www.twenga.pl/ które jest portalem o ogólnej tematyce wyszukującym ceny jedynie spośród sklepów internetowych. Obie z powyższych stron zarabiają na reklamach wystawianych na stronie. Kolejny powiązany z tematem portal to http://napiwo.org/ oferująca mapę Krakowa wraz z naniesionymi klubami i cenami piwa, witryna ta ma bardzo wąski zakres funkcjonalności i jest stworzona w celach całkowicie niekomercyjnych.
==== Analiza wymagań użytkownika (wstępna) ====
**Główne funkcjonalności (Must have):**
* rejestracja użytkowników, aktywacja, ostrzeżenia za łamanie regulaminu, banowanie, przypomnienia hasła.
* wyszukiwanie piwa według lokalizacji, przedziału cenowego, nazwy, opakowania.
* statystyki odwiedzin strony.
* integracja z API Google Maps, wyświetlenie mapy z zaznaczonymi sklepami i ich cenami.
**Dodatkowe funkcjonalności (Could have):**
* integracja z portalami społecznościowymi (wykop, facebook, blip, nasza klasa).
* informacje o promocjach.
==== Określenie scenariuszy użycia ====
- **Scenariusze dla gościa**:
- Rejestracja
- Wyszukiwanie piwa
- Przeglądanie informacji o sklepie
- **Scenariusze dla użytkownika**:
- Dostęp do serwisu:
* Logowanie
* Wylogowanie
* Przypomnienie hasła
- Zarządzanie kontem:
* Zmiana danych użytkownika
- Edycja bazy sklepów i asortymentu:
* Dodawanie sklepów
* Dodawanie piw
* Edycja piw
* Usuwanie piw
- Wyszukiwanie piwa
* Wyszukiwanie z użyciem podstawowej wyszukiwarki
* Wyszukiwanie z użyciem zaawansowanej wyszukiwarki
- Przeglądanie informacji o sklepie
- **Scenariusze dla administratora**:
- Zarządzanie piwami
* Dodawanie piwa
* Edycja piwa
* Usuwanie piwa
- Zarządzanie piwami w sklepach
* Dodawanie piwa do sklepu
* Edycja korelacji piwa ze sklepem
* Usuwanie piwa ze sklepu
- Zarządzanie miastami
* Dodawanie miasta
* Edycja miasta
* Usuwanie miasta
- Zarządzanie korporacjami
* Dodawanie korporacji
* Edycja korporacji
* Usuwanie korporacji
- Zarządzanie promocjami
* Dodawanie promocji
* Edycja promocji
* Usuwanie promocji
- Zarządzanie sklepami
* Dodawanie sklepu
* Edycja sklepu
* Usuwanie sklepu
- Zarządzanie użytkownikami:
* Zmiana danych użytkownika
* Banowanie użytkownika
- Przeglądanie ostrzeżeń
* Usuwanie ostrzeżeń
- Przeglądanie statystyk
Diagram przypadków użycia:
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:usecase.png|}}
==== Identyfikacja funkcji ====
**Część administracyjna**:
* Logowanie/wylogowywanie z panelu administracyjnego
* Dodawanie,modyfikacja,usuwanie piw
* Dodawanie,modyfikacja,usuwanie piw w sklepach
* Dodawanie,modyfikacja,usuwanie miast
* Dodawanie,modyfikacja,usuwanie korporacji handlowych
* Dodawanie,modyfikacja,usuwanie promocji
* Dodawanie,modyfikacja,usuwanie sklepów
* Dodawanie,modyfikacja,usuwanie, banowanie, aktywowanie użytkowników
* Usuwanie ostrzeżeń użytkowników
* Statystki odwiedzi
* ilość wszystkich wejść,
* wejsc unikalnych,
* typu przeglądarki internautów
**Część publiczna**:
* Logowanie/wylogowywanie z serwisu
* Rejestracja użytkownika, modyfikacja danych, przypominanie hasła
* Wyszukiwanie piwa wg ceny, marki, miasta, opakowania
* Zaawansowane wyszukiwanie piwa wg lokalizacji geograficznej
* Dodawanie sklepów, uaktualnianie asortymentu, zapisywanie ulubionych sklepów
* Dodawanie promocji, dodawanie piwa do sklepu, edycja cen, raportowanie innych użytkowników
* Integracja z portalami spolecznosciowymi
==== Analiza hierarchii funkcji projektowanej aplikacji ====
FHD - Functional Hierarchy Diagram
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:fhd.png|}}
==== Budowa i analiza diagramu przepływu danych ====
Diagram kontekstowy
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:przeplywdanych0.png|}}
Diagramy systemowe
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:przeplywdanych1a.png|}}
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:przeplywdanych1b.png|}}
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:przeplywdanych1c.png|}}
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:przeplywdanych1d.png|}}
==== Wybór encji (obiektów) i ich atrybutów ====
**BEERS**
* id int PK
* type enum('can','bottle')
* name text
* volume enum('0.33','0.5','0.65','1.0','1.5')
**BEER_STORE**
* beer_id int FK
* store_id int FK
* user_id int FK
* price double(4,2)
* last_update int
**BOOKMARKS**
* user_id int FK
* store_id int FK
**CITIES**
* id int
* name varchar(64)
**CORPORATIONS**
* id int
* name text
**PROMOTIONS**
* id int
* beer_id int FK
* corporation_id int FK
* description text
* date_start int
* date_finish int
**STATISTICS**
* id int
* browser varchar(128)
* ip varchar(15)
* date int
* user_id int FK
**STORES**
* id int
* corporation_id int FK
* name text
* city_id int FK
* address text
* description text
* latitude float(6,4)
* longitude float(6,4)
* open text
* open24h tinyint
* location point
* user_id int FK
**USERS**
* id int
* login text
* md5sum text
* email text
* privilage int
* last_change int
* last_delete int
**WARNINGS**
* id int
* user_id int FK
* warning text
==== Projektowanie powiązań (relacji) pomiędzy encjami ====
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:eer.png|}}
==== Projekt diagramów STD ====
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:std1.gif|}}
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:std2.gif|}}
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:std3.gif|}}
==== Słowniki danych ====
Specyfikacja słownika danych. Specyfikacja dziedzin i ograniczeń.
Robimy to w ogóle ?
==== Projektowanie tabel, kluczy, kluczy obcych, powiązań między tabelami, indeksów ====
CREATE SCHEMA IF NOT EXISTS mydb DEFAULT CHARACTER SET utf8 COLLATE utf8;
USE mydb;
CREATE TABLE IF NOT EXISTS mydb.cities (
id INT(11) NOT NULL AUTO_INCREMENT ,
name VARCHAR(64) NOT NULL ,
PRIMARY KEY (id) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.users (
id INT(11) NOT NULL AUTO_INCREMENT ,
login TEXT NOT NULL ,
md5sum TEXT NOT NULL ,
email TEXT NOT NULL ,
privilage INT(11) NOT NULL ,
last_change INT(11) NOT NULL ,
last_delete INT(11) NOT NULL ,
PRIMARY KEY (id) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.corporations (
id INT(11) NOT NULL AUTO_INCREMENT ,
name TEXT NOT NULL ,
PRIMARY KEY (id) )
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.stores (
id INT(11) NOT NULL AUTO_INCREMENT ,
corporation_id INT(11) NOT NULL ,
name TEXT NOT NULL ,
city_id INT(11) NOT NULL ,
address TEXT NOT NULL ,
description TEXT NOT NULL ,
latitude FLOAT NOT NULL ,
longitude FLOAT NOT NULL ,
open TEXT NOT NULL ,
open24h TINYINT(4) NOT NULL DEFAULT '0' ,
location POINT NOT NULL ,
user_id INT(11) NOT NULL ,
PRIMARY KEY (id) ,
INDEX fk_city_id (city_id ASC) ,
INDEX fk_user_id (user_id ASC) ,
INDEX fk_corporation_id (corporation_id ASC) ,
CONSTRAINT fk_city_id
FOREIGN KEY (city_id )
REFERENCES mydb.cities (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_user_id
FOREIGN KEY (user_id )
REFERENCES mydb.users (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_corporation_id
FOREIGN KEY (corporation_id )
REFERENCES mydb.corporations (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.beer_store (
beer_id INT(11) NOT NULL ,
store_id INT(11) NOT NULL ,
user_id INT(11) NOT NULL ,
price DOUBLE NOT NULL ,
last_update INT(11) NOT NULL ,
INDEX fk_beer_id (beer_id ASC) ,
INDEX fk_store_id (store_id ASC) ,
INDEX fk_user_id (user_id ASC) ,
CONSTRAINT fk_beer_id
FOREIGN KEY (beer_id )
REFERENCES mydb.beers (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_store_id
FOREIGN KEY (store_id )
REFERENCES mydb.stores (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_user_id
FOREIGN KEY (user_id )
REFERENCES mydb.users (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.bookmarks (
user_id INT(11) NOT NULL ,
store_id INT(11) NOT NULL ,
INDEX fk_user_id (user_id ASC) ,
INDEX fk_store_id (store_id ASC) ,
CONSTRAINT fk_user_id
FOREIGN KEY (user_id )
REFERENCES mydb.users (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_store_id
FOREIGN KEY (store_id )
REFERENCES mydb.stores (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.promotions (
id INT(11) NOT NULL AUTO_INCREMENT ,
beer_id INT(11) NOT NULL ,
corporation_id INT(11) NOT NULL ,
description TEXT NOT NULL ,
date_start INT(11) NOT NULL ,
date_finish INT(11) NOT NULL ,
PRIMARY KEY (id) ,
INDEX fk_corporation_id (corporation_id ASC) ,
INDEX fk_beer_id (beer_id ASC) ,
CONSTRAINT fk_corporation_id
FOREIGN KEY (corporation_id )
REFERENCES mydb.corporations (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT fk_beer_id
FOREIGN KEY (beer_id )
REFERENCES mydb.beers (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.statistics (
id INT(11) NOT NULL AUTO_INCREMENT ,
browser VARCHAR(128) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NOT NULL ,
ip VARCHAR(15) CHARACTER SET 'utf8' COLLATE 'utf8_unicode_ci' NOT NULL ,
date INT(11) NOT NULL ,
user_id INT(11) NOT NULL ,
PRIMARY KEY (id) ,
INDEX fk_user_id (user_id ASC) ,
CONSTRAINT fk_user_id
FOREIGN KEY (user_id )
REFERENCES mydb.users (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
CREATE TABLE IF NOT EXISTS mydb.warnings (
id INT(11) NOT NULL AUTO_INCREMENT ,
user_id INT(11) NOT NULL ,
warning TEXT NOT NULL ,
PRIMARY KEY (id) ,
INDEX fk_user_id (user_id ASC) ,
CONSTRAINT fk_user_id
FOREIGN KEY (user_id )
REFERENCES mydb.users (id )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8;
==== Analiza zależności funkcyjnych i normalizacja tabel ====
Wydaje nam się, że baza danych spełnia założenia 3NF. Wynika to z faktu, że przechowywane w niej dane są istotnie atomiczne - z punktu widzenia implementacji projektu. W każdej tabeli atrybuty są w pełni bezpośrednio zależne od klucza głównego. Generalnie baza była projektowana tak by przy możliwie maksymalnej funkcjonalności tabel, zapewnić trzecią postać normalną.
==== Projektowanie operacji na danych ====
SELECT b.*, bs.price as price, concat(s.name,crp.name) as store, s.id AS store_id, c.name as city, s.latitude, s.longitude
FROM beer AS b
LEFT JOIN beer_store AS bs ON b.id = bs.beer_id
JOIN stores AS s ON bs.store_id = s.id
LEFT JOIN corporation AS crp ON s.corporation_id = crp.id
LEFT JOIN city AS c ON s.city_id = c.id
SELECT s.*, c.name as corporation, t.name as city, u.login
FROM stores AS s
LEFT JOIN city AS t ON s.city_id = t.id
LEFT JOIN corporation AS c ON s.corporation_id = c.id
LEFT JOIN user AS u ON s.user_id = u.id
WHERE s.id = $id
$sql_part = "GeomFromText('Polygon((".($x-$distance)." ".($y-$distance).",".($x-$distance)." ".($y+$distance).",".($x+$distance)." ".($y+$distance).",".($x+$distance)." ".($y-$distance).",".($x-$distance)." ".($y-$distance)."))')";
SELECT * FROM stores
WHERE Contains('.$sql_part.' , location )
==== Zdefiniowanie interfejsów do prezentacji, edycji i obsługi danych ====
* Rejestracja nowego użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:rejestracja.jpg|}}
* Dodawanie nowego sklepu przez użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:dodaj_sklep.jpg|}}
* Dodawanie promocji do sklepu przez użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:dodaj_promocje.jpg|}}
* Dodawanie piwa przez użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:dodaj_piwo.jpg|}}
* Edytowanie ceny piwa przez użytkownika
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:edytuj_cene.jpg|}}
* Wyszukiwanie podstawowe
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:szukaj.jpg|}}
* Wyszukiwanie zaawansowane
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:szukaj_z.jpg|}}
==== Zdefiniowanie panelu sterowania aplikacji ====
* Panel administracyjny - lista wszystkich piw
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:admin.jpg|}}
* Panel administracyjny - dodawanie piwa
{{:pl:dydaktyka:ztb:2010:projekty:gdziepopiwo:dodaj_piwo2.jpg|}}
==== Opracowanie doświadczeń wynikających z realizacji projektu ====
Podział prac na 3 osoby dał możliwość szybkiej realizacji pracy. Każda osoba była odpowiedzialna za swoją część i sumiennie wywiązała się z zadania. Nie wiem co tu można lepszego napisać. Przecież nikt nie liczył mandaysów.
==== Literatura ====
* http://www.spatial.cs.umn.edu/Book/labs/vania/spatialQueries.html
* http://postgis.refractions.net
* http://wb.mysql.com