Релационен модел
ЕР дијаграм
Архитектура и главни концепти
Корисници и нивни улоги
Основна е поделбата меѓу users (сите во системот), drivers (возачи) и passengers (патници). Табелата users е како „мајка“ — ги содржи основните информации (име, телефон, е-пошта). Потоа drivers и passengers ги додаваат своите специфични полиња. Една иста личност може да биде и возач и патник — нема никаква забрана за тоа.
Возила и производители
Возилата се организирани во три нивоа. Прво manufacturers (Volkswagen, Mercedes итн.), потоа vehicle_models (Golf, C-Class), па самите vehicles (твојата лична кола). Ваквото расчленување спречува да се пишува "Volkswagen" стотици пати во базата.
Возачот може да има многу возила, а секое возило мора да припаѓа на возач. За тоа ја користиме vehicle_ownership — табела која чува податоци за тоа кој возач кој автомобил го поседувал. Кога возачот ќе купи ново возило, едноставно додаваме нов ред во vehicle_ownership. Старото возило останува во историјата и не го бришеме. На овој начин точно гледаме кој возач во кој период поседувал одредена кола.
Рути и возења
Routes е шаблон — на пример рута „Скопје → Куманово → Прилеп“ која е веќе дефинирана во системот. Rides е конкретно возење: „Во понеделник во 08:00 часот возачот Марко ја возеше оваа рута со Volkswagen Golf“.
Застанувањата на рутата се чуваат во route_stops со редоследни броеви (1, 2, 3...). Рутата може да има 2 застанувања или 10 застанувања. Исто така, на иста рута може да се направи и круг (почетокот и крајот да се на иста локација).
Сегменти — како се делат возењата
Возењето од Скопје до Прилеп преку Куманово не е „целина“ во пресметките. Поделено е на сегменти:
- Скопје → Куманово
- Куманово → Прилеп
Патниците не мора да ја патуваат целата рута. Еден патник може да влезе во Куманово и да излезе во Прилеп. Затоа route_segments ја дели рутата на делови меѓу два стопа, а passenger_segments чува податоци за тоа колку патници имало на секој сегмент. Вака точно можеме да пресметаме колку треба да плати секој патник според тоа каде влегол и каде слегол.
Патарини
Не можеме едноставно да кажеме дека „возењето чини X денари“. Некои возења поминуваат низ наплатни рампи. За тоа имаме:
toll_points— каде се наплатните рампи и колку чинат според типот на возилоride_tolls— евидентира дека возењето Х поминало низ рампата Ytoll_passenger_split— поделба на патарината меѓу патниците кои биле присутни
Готовина, а не картички
Апликацијата работи исклучиво со готовина. Нема онлајн плаќања, ниту дигитални паричници. Возачот ја собира готовината од патниците. Табелите fare_splits и booking_final_fare служат само за да му покажат на возачот колку пари треба да собере од кого — ништо повеќе.
Оценувања
Патниците ги оценуваат возачите, а возачите ги оценуваат патниците. Табелата ratings ги чува сите оценувања. Постои CHECK constraint кој вели: „Корисникот не може да се оцени самиот себеси“. За просечната оцена не користиме директно поле avg_rating. Наместо тоа, користиме погледи (views) driver_ratings и passenger_ratings кои го пресметуваат просекот во реално време (on the fly). Вака, ако додадеш нова оценка, просекот се ажурира веднаш без дополнителна логика.
Историја и следливост
Кога возењето ќе го промени статусот (scheduled → in_progress → completed), промената се запишува во ride_status_history со временска ознака. Истото важи и за резервациите во booking_status_history. На овој начин администраторот има целосна историја — кога точно што се случило.
Бришење на податоци
Претпоставка: администраторот брише кориснички профил. Но возачот има 50 завршени возења! Ние не ги бришеме поврзаните возења — користиме ON DELETE RESTRICT. За потребите на статистиката, користиме резервиран корисник со id = 0 наречен „избришан корисник“. Така можеме да видиме дека „некој возач“ направил возење, дури и кога оригиналниот профил е избришан.
Прегледи (Views)
Сите овие табели се поврзани со JOIN-ови. Наместо апликацијата да пишува SELECT ... FROM rides JOIN drivers JOIN vehicles ... низ целиот код, направивме 9 погледи (views). Секој поглед е подготвена SQL „забелешка“ која се однесува како табела.
v_available_rides — Возења отворени за резервирање
Ова е она што патникот го гледа кога пребарува возење. Прикажува:
- Кога поаѓа возењето
- Каде почнува, а каде завршува
- Име на возачот
- Марка и модел на возилото
- Проценета цена
- Просечна оцена на возачот
Овој VIEW прави JOIN меѓу rides, drivers, vehicles, vehicle_models, manufacturers, routes, route_stops, ratings и го пресметува просекот на оценките во реално време. Ги филтрира само возењата со статус scheduled.
Апликацијата го користи вака: SELECT * FROM v_available_rides WHERE origin_city = 'Скопје' AND departure_time >= NOW(). Едноставно!
v_driver_profile — Профил на возачот
Возачот го гледа ова кога го ажурира својот профил. Исто така, патникот го гледа ова пред да резервира место ако сака да види со кого ќе се вози.
Содржи:
- Лични податоци (име, телефон)
- Информации за возачка дозвола (број, датум на издавање)
- Примарното возило на возачот (ако има повеќе, го земаме она со најмал ID)
- Статистика: вкупно возења, завршени, откажани
- Просечна оцена
VIEW-то прави JOIN меѓу drivers, users, driver_licenses, vehicles, vehicle_ownership, rides и ratings. Ги пресметува бројот на возења според статус и просекот на оценките.
v_passenger_trip_history — Моја патна историја
Патникот, кога ќе кликне на „Мои патувања“, го гледа следново:
- Кога било возењето
- Каде почнало, а каде завршило
- Име на возачот
- Потврда дека е качен (pickup_confirmed_at)
- Потврда дека е слезен (dropoff_confirmed_at)
- Колку платил
- Неговата оценка за возачот (ако ја дал)
Секоја резервација е посебен ред во погледот. Апликацијата може лесно да филтрира по статус (completed, canceled) или да ги пагинира резултатите.
v_ride_manifest — Список на патници за возење
Возачот одлучува да тргне во 08:00 часот. Пред да го запали возилото, ја отвора оваа листа за да види:
- Кои патници се качуваат
- Имиња и телефонски броеви
- Каде влегува секој (point_A_stop)
- Каде слегува секој (point_B_stop)
- Колку пари треба да собере од секого
Ги прикажува само резервациите со статус confirmed, picked_up или completed. Откажаните резервации не се прикажуваат — нема смисла возачот да ги гледа.
v_booking_details — Целосни детали за резервација
Патникот кликнува на една резервација и гледа „сè на едно место“:
- Кој е возачот (име, телефон, оцена)
- Какво возило (марка, модел, регистарски таблички)
- Точна локација за качување (на пр. Централна станица, Скопје)
- Точна локација за слегување (на пр. Куманово центар)
- Точен час на поаѓање
- Финална цена
- Статус на резервацијата
Содржи многу JOIN-ови, па затоа апликацијата СЕКОГАШ го повикува со филтер: WHERE booking_id = 123. Никогаш не се повикува без филтер за да не се преоптовари базата.
v_unread_notifications — Мои нови известувања
Патникот или возачот го отвораат „ѕвончето“. Ги гледаат само непрочитаните известувања:
- Текстот на известувањето
- Од кого е испратено (возач, администратор итн.)
- Кога е испратено (точно време или „пред 5 минути“)
VIEW-то ја пресметува „староста во минути“ за да прикаже „пред 5 мин“ без дополнителна логика во апликацијата. Апликацијата го повикува со WHERE user_id = 42 AND read_at IS NULL.
v_driver_earnings — Мои месечни приходи
Возачот кликнува на „Финансиски извештај“ и гледа:
- Колку возења направил за секој месец
- Колку резервации наплатил (некои можеби биле откажани во последен момент)
- Вкупен приход
- Просечен приход по резервација
- Максимален приход
- Минимален приход
Администраторот го користи ова и за анализа — ако возачот нема приход три месеци, веројатно е неактивен. Пресметката се базира на bookings со статус completed и нивните финални суми.
v_route_popularity — Кои рути се најпопуларни
Апликацијата на почетниот екран прикажува популарни рути за да го мотивира патникот. Овој поглед ги рангира рутите според:
- Број на вкупни резервации
- Просечна цена по резервација
- Просечна цена по километар
Служи и како сигнал за возачите. Ако рутата Скопје↔Куманово има 50 резервации месечно, а возачот направил 10 возења и не продал ништо — тоа е знак дека нешто не е во ред (можеби е прескапо или возењето не е добро рекламирано).
v_incident_summary — Безбедносни инциденти
Ова го гледа само администраторот. Прикажува:
- Тип на инцидент (некултурно однесување, несреќа, кршење правила)
- Опис на инцидентот
- Кога е пријавен
- Лични податоци на пријавувачот (патник или возач)
- Лични податоци на другата страна
- Број на возачка дозвола
- Рута на возењето
Инцидентите можат да бидат пријавени дури и по завршено возење, па затоа овој поглед не филтрира според статусот на возењето.
Важно: NULL вредности со логика
Неколку полиња се NULL врз основа на одредена логика:
rides.recurrence_daysиrides.recurrence_end_date— се пополнуваат САМО акоis_recurring = TRUE. За еднократни возења тие се NULL.bookings.pickup_stop_idиbookings.dropoff_stop_id— ако патникот ја резервира целата рута, стоповите се почетната и крајната точка. Ако резервира само дел, се пополнуваат конкретните стопови.
Апликацијата треба да ги проверува овие услови пред да ги користи вредностите.
Attachments (3)
- RelationalModel.jpg (249.3 KB ) - added by 2 weeks ago.
- RelationalModel.zip (60.3 KB ) - added by 13 days ago.
- RelationalModel-drive-net.svg (481.4 KB ) - added by 11 days ago.
Download all attachments as: .zip
