Projekt obejmuje stworzenie systemu wspierającego wymianę przedmiotów typu książki, płyty CD oraz DVD, gry komputerowe oraz gry planszowe pomiędzy zarejestrowanymi użytkownikami. Na rynku nadal istnieje deficyt serwisów oferujących tego typu usługi a wielu ludzi po pewnym czasie użytkowania przedmiotów są skłonni wymienić je na inne tego samego typu. Pozwala to zaoszczędzić pieniądze wydane na kupowanie wciąż nowych produktów. Serwis ten umożliwia odnalezienie ludzi posiadających interesujące danego użytkownika przedmioty oraz bezproblemową wymianę. Istniejące w Internecie podobne serwisy internetowe nie są w pełni funkcjonalne, dlatego motywacją jest utworzenie systemu bardziej spełniającego zadania stawiane takiemu serwisowi. Rejestracja w serwisie będzie bezpłatna, jednak konto podstawowe oferować będzie ograniczone funkcje wymiany przedmiotów. Użytkownicy będą mieli możliwość wykupienia wersji Premium, która umożliwi korzystanie ze wszystkich usług bez ograniczeń. Istniejące serwisy zajmujące się podobnym zakresem usług, działają na różnych zasadach i ich regulaminy mogą być niekorzystne dla niektórych użytkowników. Serwis Wymiennik będzie miał zasady jasno określone, odpowiadające potrzebom użytkowników oraz spełniające ich oczekiwania.
Istniejącymi na rynku rozwiązaniami tego typu to na przykład serwisy freeko.pl oraz podaj.net, jednak różnią się one zasadami wymiany od naszego serwisu. W pierwszym z nich, użytkownik, chcąc zamówić dany przedmiot, nie musi z jego właścicielem wymieniać się na produkty. Płaci on bowiem punktami freeko, które otrzymuje, oddając swoje przedmioty innym użytkownikom. Nowo zarejestrowany użytkownik nie może więc zamówić interesującego go przedmiotu, lecz najpierw musi zdobyć punkty freeko. Wystawienie przedmiotów również kosztuje, opłaca się to punktami kredytowymi. Istnieje możliwość ich dokupywania. Są one niezbędne zarówno podczas transakcji oddania przedmiotu jak i zamawiania. Serwis podaj.net działa w podobny sposób: użytkownicy ‘podający’ przedmioty innym użytkownikom zbierają punkty, które mogą następnie wykorzystać, gdy chcą wypożyczyć interesujący ich przedmiot. Istnieje tu pewne ograniczenie, ponieważ nowi użytkownicy nie posiadający punktów nie mogą pożyczać produktów. Serwis podaj.pl oferuje jednak dokupowanie punktów. Istnieje również możliwość przelewania punktów dowolnym użytkownikom. W odróżnieniu od istniejących już na rynku portali tego typu, serwis Wymiennik umożliwia wymianę przedmiotów nawet nowo zarejestrowanym użytkownikom w koncie podstawowym, co w przeciwieństwie do niektórych portali tego typu istniejących na rynku jest usługą całkowicie bezpłatną. Jedyną różnicą między kontem podstawowym a Premium jest ograniczenie wymiany dla użytkowników z tego samego województwa dla użytkowników posiadających pierwszy z nich. Oprócz tego, wystawienie przedmiotu do wymiany nie będzie wymagało żadnych dodatkowych opłat, co umożliwi użytkowników wprowadzanie bazy wszystkich swoich produktów. Wpłynie to znacznie na zwiększenie liczby dostępnych produktów i zwiększy szansę na znalezienie interesującego przedmiotu. Wymiana przedmiotów w serwisie Wymiennik jest możliwa tylko na zasadzie wzajemnej wymiany produktów, a nie jak w opisywanych wyżej serwisach na zasadzie zdobywanych punktów. Jest to duże udogodnienie dla użytkowników, których przedmioty wypożycza wiele innych osób, lecz oni sami nie znajdują interesujących ich pozycji.
W projekcie wyróżnia się trzy rodzaje użytkowników: Administrator serwisu, użytkownik zarejestrowany użytkownik oraz gość. Administrator zarządza całym serwisem oraz bazą danych, użytkownik zarejestrowany po zalogowaniu ma między innymi dostęp do swojego konta, edytowania go, pogląd i edycja przedmiotów oraz ich rezerwacja. Gość może jedynie przeglądać przedmioty znajdujące się w bazie jednak bez możliwości ich rejestracji. Funkcjonalności serwisu:
3.1. Must
3.2. Should
3.3. Could
4.1. Rejestracja użytkownika
4.2. Logowanie do portalu
4.3. Wyszukiwanie przedmiotu
4.4. Wyświetlanie wszystkich przedmiotów
4.5. Rezerwacja przedmiotu
4.6. Edycja danych
4.7. Dokonywanie wymiany
4.8. Anulowanie rezerwacji na swoje przedmioty
4.9. Anulowanie swoich rezerwacji
4.10. Edycja przedmiotów
4.11. Usuwanie przedmiotu
4.12. Wprowadzenie nowego przedmiotu
4.13. Sprawdzenie historii transakcji
4.14. Ocena innego użytkownika
4.15. Generowanie statystyk
4.16. Wyświetlenie Frequently Asked Questions
Object
LogUser
TransactionHistory
Faq
CREATE DATABASE Wymiennik; CREATE TABLE LogUser ( login nvarchar(50) PRIMARY KEY, password nvarchar(50) NOT NULL, name nvarchar(30) NOT NULL, surname nvarchar(50) NOT NULL, street nvarchar(50) NOT NULL, city nvarchar(50) NOT NULL, postalcode nchar(6) NOT NULL, house_nr nvarchar(50) NOT NULL, local_nr nvarchar(50), province nvarchar(50) NOT NULL, email nvarchar(50) NOT NULL, premium nchar(1) default ‘N’, avatar image, grupa nvarchar(50) NOT NULL, img_content_type nvarchar(50), note int default 0, note_count int default 0, ); CREATE TABLE Object ( objectID int IDENTITY(1,1) PRIMARY KEY, login nvarchar(50) NOT NULL references LogUser(login), title nvarchar(50) NOT NULL, author nvarchar(50) NOT NULL, year int NOT NULL, describe nvarchar(max) NULL, quality nvarchar(10) NULL, kind nvarchar(30) NOT NULL, status nvarchar(20) NOT NULL, picture image, img_type nvarchar(50), login_rezerwacji nvarchar(50) NULL references LogUser(login) ); CREATE TABLE TransactionHistory ( transactionID int IDENTITY(1,1) PRIMARY KEY, objectID1 int NOT NULL references Object(objectID), objectID2 int NOT NULL references Object(objectID), date datetime NOT NULL ); CREATE TABLE Faq( FaqID int IDENTITY(1,1) PRIMARY KEY, question nvarchar(max) NOT NULL, answer nvarchar(max) NOT NULL, views int NOT NULL default 0 ); ALTER TABLE TransactionHistory ADD CONSTRAINT DF_Transaction_date DEFAULT (getdate()) FOR date; ALTER TABLE Object ADD CONSTRAINT DF_Object_status DEFAULT ('Wolny') FOR status; ALTER TABLE Object WITH CHECK ADD CONSTRAINT CK_Object_Kind CHECK((kind='Gra_komp' OR kind='Gra_plan' OR kind='Ksiazka' OR kind='Muzyka' OR kind='Film')); ALTER TABLE Object CHECK CONSTRAINT CK_Object_Kind; ALTER TABLE Object WITH CHECK ADD CONSTRAINT CK_Object_Status CHECK(status='Wolny' OR status='Zarezerwowany' OR status='Wymieniony'); ALTER TABLE Object CHECK CONSTRAINT CK_Object_Status;
Object – tabela przechowująca dane o przedmiotach
LogUser – tabela przechowująca dane o użytkownikach
TransactionHistory – tabela przechowująca dane o wykonanych transakcjach
Faq
Pierwsza postać normalna – 1NF – spełniona, ponieważ:
Druga postać normalna – 2NF – spełniona, ponieważ:
Trzecia postać normalna – 3NF – spełniona, ponieważ:
INSERT INTO LogUser(login, password, email, name, surname, street, city, province, postalcode, grupa, house_nr, local_nr, premium, awatar, img_content_type) VALUES ( 'Melodi', 'haslo' , 'melodi@onet.pl', 'Ewelina' , 'Grybowicz', 'Mazowiecka', 'Poznań', 'wielkopolskie', '52-242', 'LogUser', 12, 4 ,'N', <Binary data>, 'image/jpeg');
UPDATE LogUser SET city='Białystok', street='Sienkiewicza', house_nr='3', local_nr='2', postalcode='15-800', avatar=@img_data, img_content_type=@img_type WHERE login='login1';
UPDATE [LogUser] SET note=@usNote, note_count=@count WHERE (login='login1')";
INSERT INTO Object (login, title, author, year, describe, quality, kind, picture, img_type ) VALUES ('Melodi', 'Rok 1984','Orwell George',1949,'Losy Georga Orwella, angielskiego pisarza urodzonego w Indiach, były bardzo burzliwe. Z przekonania socjalista, wnikliwy obserwator świata, imał się różnych słabo płatnych zajęć, które jednak inspirowały go do pisania kolejnych dzieł. Znakomicie orientował się w sytuacji politycznej na arenie międzynarodowej i rozumiał niebezpieczeństwo związane z ustrojem komunistycznym. ','dobra','Ksiazka', <Binary data>, 'image/jpeg');
UPDATE Object SET Title= @Title, Author= @Author, Year= @Year, Describe= @Describe, Quality= @Quality, status= @status WHERE (objectID = @objectID);
SELECT * FROM Object WHERE (((status = @status) OR (status] = @status2) AND (kind = @kind));
SELECT title, author, year, objectID FROM Object NATURAL JOIN LogUser WHERE (kind = 'Film' AND title like 'szukany' AND (status='Zarezerwowany' OR status='Wolny') AND province='małopolskie');
SELECT title, author, year, objectID FROM Object WHERE (kind = 'Film' AND title like 'szukany' AND (status='Zarezerwowany' OR status='Wolny'));
SELECT * FROM Object WHERE (objectID = @objectID);
UPDATE Object SET Title= @Title, Author= @Author, Year= @Year, Describe= @Describe, Quality= @Quality FROM Object WHERE (objectID = @objectID);
DELETE FROM Object WHERE (objectID=20);
UPDATE Object SET status='Zarezerwowany', login_rezerwacji='login1' FROM Object WHERE (objectID=20);
UPDATE Object SET status='Wolny', login_rezerwacji='' FROM Object WHERE (objectID=5);
SELECT title, author, year, kind, objectID, status, login_rezerwacji FROM Object WHERE (login = 'login1') AND (status='Zarezerwowany' OR status='Wolny');
SELECT title, login_rezerwacji, objectID FROM Object WHERE (login = 'login1' AND status='Zarezerwowany');
SELECT OBJ1.title AS title, OBJ2.title AS title2, OBJ2.login_rezerwacji,T.date FROM Object OBJ1 JOIN TransactionHistory T ON T.objectID1=OBJ1.objectID JOIN Object OBJ2 ON T.objectID2=OBJ2.objectID WHERE (OBJ2.login='przykladowy') UNION SELECT OBJ1.title AS title, OBJ2.title AS title2, OBJ1.login_rezerwacji,T.date FROM Object OBJ1 JOIN TransactionHistory T ON T.objectID1=OBJ1.objectID JOIN Object OBJ2 ON T.objectID2=OBJ2.objectID WHERE (OBJ1.login='przykladowy');
SELECT * FROM Faq;
SELECT * FROM Faq WHERE (ID = @ID);
SELECT count(*) FROM LogUser;
SELECT count(*) FROM Transactions
SELECT count(*) FROM Object
INSERT INTO TransactionHistory (objectID1, objectID2, date) VALUES (@object1, @object2, @dat);
UPDATE Object SET status='Wymieniony', login_rezerwacji=@ja WHERE objectID=@object1;
String us = LogUser.Identity.Name; obj1 = Request.QueryString["objectID1"]; obj2 = Request.QueryString["objectID2"]; String connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString; SqlConnection conn = new SqlConnection(); conn.ConnectionString = connectionString; conn.Open(); trans = conn.BeginTransaction(System.Data.IsolationLevel.Serializable); try { using (SqlCommand command1 = new SqlCommand()) { command1.Connection = conn; command1.Transaction = trans; command1.CommandType = CommandType.Text; command1.CommandText = string.Format("INSERT INTO TransactionHistory ([objectID1], [objectID2],[date]) VALUES (@object1, @object2, @dat)"); command1.Parameters.Add("@object1", SqlDbType.Int).Value = obj1; command1.Parameters.Add("@object2", SqlDbType.Int).Value = obj2; command1.Parameters.Add("@dat", SqlDbType.DateTime).Value = DateTime.Now; success = (command1.ExecuteNonQuery() == 1); } using (SqlCommand command2 = new SqlCommand()) { command2.Connection = conn; command2.Transaction = trans; command2.CommandType = CommandType.Text; command2.CommandText = string.Format("UPDATE Object SET status='Wymieniony', login_rezerwacji=@ja WHERE objectID=" + obj1); command2.Parameters.Add("@ja", SqlDbType.NVarChar).Value = us; success = (command2.ExecuteNonQuery() == 1); } using (SqlCommand command3 = new SqlCommand()) { command3.Connection = conn; command3.Transaction = trans; command3.CommandType = CommandType.Text; command3.CommandText = string.Format("UPDATE Object SET status='Wymieniony' WHERE objectID=" + obj2); success = (command3.ExecuteNonQuery() == 1); } } catch (SqlException ex) { success = false; } catch (Exception ex) { success = false; } finally { if (success) { trans.Commit(); wynikLabel.Text = "Wymiana została zatwierdzona!"; } else { trans.Rollback(); wynikLabel.Text = "Wymiana się nie powiodła!"; } if (conn != null) conn.Close(); }
Implementacja bazy danych została wykonana zgodnie z diagramem erd_bazy.pdf przygotowanym w poprzednich częściach. Została wykonana kopia zapasowa bazy danych. Wykorzystano przy tym polecenie:
BACKUP DATABASE [Wymiennik.mdf] TO DISK='d:\Wymiennik.bak'
Baza została utworzona za pomocą systemu Microsoft SQL Server w oparciu o kod podany poniżej.
CREATE DATABASE Wymiennik; CREATE TABLE LogUser ( login nvarchar(50) PRIMARY KEY, password nvarchar(50) NOT NULL, name nvarchar(30) NOT NULL, surname nvarchar(50) NOT NULL, street nvarchar(50) NOT NULL, city nvarchar(50) NOT NULL, postalcode nchar(6) NOT NULL, house_nr nvarchar(50) NOT NULL, local_nr nvarchar(50), province nvarchar(50) NOT NULL, email nvarchar(50) NOT NULL, premium nchar(1) default ‘N’, avatar image, grupa nvarchar(50) NOT NULL, img_content_type nvarchar(50), note int default 0, note_count int default 0, ); CREATE TABLE Object ( objectID int IDENTITY(1,1) PRIMARY KEY, login nvarchar(50) NOT NULL references LogUser(login), title nvarchar(50) NOT NULL, author nvarchar(50) NOT NULL, year int NOT NULL, describe nvarchar(max) NULL, quality nvarchar(10) NULL, kind nvarchar(30) NOT NULL, status nvarchar(20) NOT NULL, picture image, img_type nvarchar(50), login_rezerwacji nvarchar(50) NULL references LogUser(login) ); CREATE TABLE TransactionHistory ( transactionID int IDENTITY(1,1) PRIMARY KEY, objectID1 int NOT NULL references Object(objectID), objectID2 int NOT NULL references Object(objectID), date datetime NOT NULL ); CREATE TABLE Faq( FaqID int IDENTITY(1,1) PRIMARY KEY, question nvarchar(max) NOT NULL, answer nvarchar(max) NOT NULL, views int NOT NULL default 0 ); ALTER TABLE TransactionHistory ADD CONSTRAINT DF_Transaction_date DEFAULT (getdate()) FOR date; ALTER TABLE Object ADD CONSTRAINT DF_Object_status DEFAULT ('Wolny') FOR status; ALTER TABLE Object WITH CHECK ADD CONSTRAINT CK_Object_Kind CHECK ((kind='Gra_komp' OR kind='Gra_plan' OR kind='Ksiazka' OR kind='Muzyka' OR kind='Film')); ALTER TABLE Object CHECK CONSTRAINT CK_Object_Kind; ALTER TABLE Object WITH CHECK ADD CONSTRAINT CK_Object_Status CHECK (status='Wolny' OR status='Zarezerwowany' OR status='Wymieniony'); ALTER TABLE Object CHECK CONSTRAINT CK_Object_Status;
Panel administracyjny użytkownika pozwala na edycję danych użytkownika, dodawanie, usuwanie oraz edycję jego przedmiotów. Umożliwia również na zarządzanie rezerwacjami danego użytkownika, jak również rezerwacją jego przedmiotów.
Aplikacja była stworzona używając narzędzia Visual Web Developer 2010 Express oraz wykorzystaniu lokalnie zainstalowanego silnika baz danych SQL Server 2008. Podczas testowania była ona uruchamiana na lokalnym serwerze przy użyciu przeglądarek Google Chrome oraz Mozilla Firefox. Testowanie polegało na sprawdzaniu każdej funkcjonalności oddzielnie, a następnie w połączeniu z innymi modułami.
W danej aplikacji nie ma potrzeby automatycznego wprowadzania danych lub importowania ich. Każdy użytkownik za pomocą narzędzi zdefiniowanych w aplikacji może w łatwy sposób ręcznie wprowadzić jego przedmioty.
Wdrożenie systemu do użytkowania będzie polegało na właściwych skonfigurowaniu aplikacji oraz bazy danych na zdalnym serwerze.
Aplikacja nie jest skomplikowana, dlatego żadne szkolenia nie są wymagane. W razie jakichkolwiek niejasności można przeszukać Frequently Asked Questions w poszukiwaniu odpowiedzi na niejasne pytania lub skontaktować się z administratorem portalu.
Dokumentacja użytkowa nie jest wymagana, jako że aplikacja jest bardzo intuicyjna oraz prosta w obsłudze.
Od strony technicznej serwisem będzie zarządzał administrator.
Aplikacja została tak zaprojektowana, że jej rozwój jest w zasadzie nieograniczony. Kolejnym etapem byłoby zwiększenie ilości kategorii przedmiotów, jest to proste w zaimplementowaniu, a może wzbogacić serwis o wielu nowych użytkowników, jak również przedmiotów. Po pewnym czasie może zmienić się również skala wymiany przedmiotów, na przykład na inne kraje, co wiązałoby się z translacją serwisu na inne języki. Można również łatwo dodawać wiele nowych funkcjonalności takich jak wystawianie komentarzy innym użytkownikom, wysyłanie wiadomości pomiędzy użytkownikami, integracje z systemami płatności PayPal lub portalami społecznościowymi.
W projekcie najwięcej problemów przysporzyło poznanie nowej technologii, w której żaden z członków zespołu wcześniej nie pracował. Jednak po pokonaniu początkowych trudności tworzenie projektu przebiegało pomyślnie a programowanie z wykorzystaniem platformy .NET okazało się dość intuicyjne. Zapewniona dobra obsługa bazy danych MS SQL Server sprawiła, że projekt powstawał w wyznaczonym czasie bez zastojów w projektowaniu.