Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/BusNGoBackendApplication.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/BusNGoBackendApplication.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/BusNGoBackendApplication.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,39 @@
+package mk.ukim.finki.busngobackend
+
+import org.springframework.boot.autoconfigure.SpringBootApplication
+import org.springframework.boot.runApplication
+import org.springframework.context.annotation.Bean
+import org.springframework.context.event.ApplicationEventMulticaster
+import org.springframework.context.event.SimpleApplicationEventMulticaster
+import org.springframework.core.task.SimpleAsyncTaskExecutor
+import org.springframework.scheduling.annotation.EnableAsync
+import org.springframework.scheduling.annotation.EnableScheduling
+import org.springframework.security.crypto.password.NoOpPasswordEncoder
+import org.springframework.security.crypto.password.PasswordEncoder
+
+@SpringBootApplication
+@EnableAsync
+@EnableScheduling
+class BusNGoBackendApplication
+
+fun main(args: Array<String>) {
+    runApplication<BusNGoBackendApplication>(*args)
+}
+
+@Bean
+fun encoder(): PasswordEncoder = NoOpPasswordEncoder.getInstance()
+//    object : PasswordEncoder {
+//        override fun encode(rawPassword: CharSequence?): String = rawPassword.toString()
+//
+//        override fun matches(
+//            rawPassword: CharSequence?,
+//            encodedPassword: String?,
+//        ): Boolean = rawPassword != null && rawPassword.toString() == encodedPassword
+//    }
+
+@Bean
+fun asyncEventPublisher(): ApplicationEventMulticaster {
+    val publisher = SimpleApplicationEventMulticaster()
+    publisher.setTaskExecutor(SimpleAsyncTaskExecutor())
+    return publisher
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/AdminController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/AdminController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/AdminController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,40 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.service.AdminService
+import org.springframework.web.bind.annotation.*
+
+@RestController
+@RequestMapping("/api/admin")
+class AdminController(
+    private val adminService: AdminService,
+) {
+    @GetMapping("/average-time-between-stations")
+    fun getAvgTimeBetweenStations() = adminService.getAverageTimeBetweenStations()
+
+    @GetMapping("/fines-by-line")
+    fun getFinesByLine() = adminService.getFinesByLine()
+
+    @GetMapping("/commutes-by-hour")
+    fun getCommutesByHour() = adminService.getCommutesByHour()
+
+    @GetMapping("/commutes-by-line")
+    fun getCommutesByLine() = adminService.getCommutesByLine()
+
+    @GetMapping("/number-of-passengers-per-line-and-station")
+    fun getNumberOfPassengersPerLineAndStation() = adminService.getNumberOfPassengersByLineAndStation()
+
+    @GetMapping("/ticket-sales")
+    fun getTicketSales() = adminService.getTicketSales()
+
+    @GetMapping("/total-income")
+    fun getTotalIncome() = adminService.getTotalIncome()
+
+    @GetMapping("/all-users")
+    fun getAllUsers() = adminService.getAllUsers()
+
+    @PostMapping("/update-roles/{id}")
+    fun updateRolesForUser(
+        @PathVariable id: Long,
+        @RequestBody roles: List<String>,
+    ) = adminService.updateRolesForUser(id, roles)
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/AuthController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/AuthController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/AuthController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,29 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.api.requests.AuthRequest
+import mk.ukim.finki.busngobackend.api.requests.RegisterRequest
+import mk.ukim.finki.busngobackend.api.responses.AuthResponse
+import mk.ukim.finki.busngobackend.service.AuthService
+import org.springframework.web.bind.annotation.*
+
+@RestController
+@RequestMapping("/api/auth")
+class AuthController(
+    private val authService: AuthService,
+) {
+    @GetMapping()
+    fun isAuthenticated() = authService.isAuthenticated()
+
+    @PostMapping("/register")
+    fun register(
+        @RequestBody registerRequest: RegisterRequest,
+    ): AuthResponse = authService.register(registerRequest)
+
+    @PostMapping()
+    fun authenticate(
+        @RequestBody authRequest: AuthRequest,
+    ): AuthResponse = authService.authenticate(authRequest)
+
+    @GetMapping("/is-driver-free")
+    fun isDriverFree() = this.authService.isDriverFree()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/BusController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/BusController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/BusController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.service.BusService
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/buses")
+class BusController(
+    private val busService: BusService,
+) {
+    @GetMapping("")
+    fun getAllBuses() = busService.findAll()
+
+    @GetMapping("/free")
+    fun getAllFrees() = busService.findAllFree()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/ChatController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/ChatController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/ChatController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,26 @@
+package mk.ukim.finki.busngobackend.api
+
+import org.springframework.messaging.handler.annotation.MessageMapping
+import org.springframework.messaging.handler.annotation.Payload
+import org.springframework.messaging.handler.annotation.SendTo
+import org.springframework.messaging.simp.SimpMessageHeaderAccessor
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+class ChatController {
+    @MessageMapping("/chat.sendMessage")
+    @SendTo("/topic/public")
+    fun sendMessage(
+        @Payload message: String,
+    ): String = message
+
+    @MessageMapping("/chat.addUser")
+    @SendTo("/topic/public")
+    fun addUser(
+        @Payload message: String,
+        headerAccessor: SimpMessageHeaderAccessor,
+    ): String {
+        headerAccessor.sessionAttributes?.put("username", message)
+        return message
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/CommuteController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/CommuteController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/CommuteController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,23 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.api.requests.StartCommuteRequest
+import mk.ukim.finki.busngobackend.service.CommuteService
+import org.springframework.web.bind.annotation.PutMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/commutes")
+class CommuteController(
+    private val commuteService: CommuteService,
+) {
+    @PutMapping("/start")
+    fun startCommute(
+        @RequestBody request: StartCommuteRequest,
+    ) = commuteService.start(request)
+
+    // subscribe to the topic for that station
+    // receive the incoming route instances
+    // choose one as target and start commute
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/ControlsController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/ControlsController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/ControlsController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,23 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.service.ControlService
+import org.springframework.web.bind.annotation.*
+
+@RestController
+@RequestMapping("/api/controls")
+class ControlsController(
+    private val controlService: ControlService,
+) {
+    @GetMapping()
+    fun getControls() = controlService.getAllByConductor()
+
+    @PutMapping("/start")
+    fun start(
+        @RequestBody routeInstanceId: Long,
+    ) = controlService.start(routeInstanceId)
+
+    @GetMapping("/{controlId}/fines")
+    fun getFines(
+        @PathVariable controlId: Long,
+    ) = controlService.getFines(controlId)
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/DummyDataPopulatorController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/DummyDataPopulatorController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/DummyDataPopulatorController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,21 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.simulator.DummyDataPopulator
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/dummy")
+class DummyDataPopulatorController(
+    private val dummyDataPopulator: DummyDataPopulator,
+) {
+    @GetMapping("/route-instances")
+    fun populateRouteInstances() = dummyDataPopulator.populateRouteInstances()
+
+    @GetMapping("/commutes")
+    fun populateCommutes() = dummyDataPopulator.populateCommutes()
+
+    @GetMapping("/fines")
+    fun populateFines() = dummyDataPopulator.populateFines()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/FineController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/FineController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/FineController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,19 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.api.requests.FineRequest
+import mk.ukim.finki.busngobackend.service.FineService
+import org.springframework.web.bind.annotation.PutMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/fines")
+class FineController(
+    private val fineService: FineService,
+) {
+    @PutMapping()
+    fun createFine(
+        @RequestBody request: FineRequest,
+    ) = fineService.createFine(request)
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/LineController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/LineController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/LineController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,28 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.service.DirectionService
+import mk.ukim.finki.busngobackend.service.LineService
+import mk.ukim.finki.busngobackend.service.StationService
+import org.springframework.web.bind.annotation.*
+
+@RestController
+@RequestMapping("/api/lines")
+class LineController(
+    private val lineService: LineService,
+    private val directionService: DirectionService,
+    private val stationService: StationService,
+) {
+    @GetMapping("")
+    fun getLines() = lineService.findAllLines()
+
+    @GetMapping("/{id}/directions")
+    fun getLineDirections(
+        @PathVariable("id") lineId: Int,
+    ) = directionService.findDirectionsByLineId(lineId)
+
+    @GetMapping("/{lineId}/stations")
+    fun getLineStations(
+        @PathVariable("lineId") lineId: Int,
+        @RequestParam("directionId", required = false) directionId: Long,
+    ) = stationService.findStationsByLineIdAndDirectionId(lineId, directionId)
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/RouteInstanceController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/RouteInstanceController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/RouteInstanceController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,34 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.api.requests.StartRouteInstanceRequest
+import mk.ukim.finki.busngobackend.service.RouteInstanceService
+import org.springframework.web.bind.annotation.*
+
+@RestController
+@RequestMapping("/api/route-instances")
+class RouteInstanceController(
+    private val routeInstanceService: RouteInstanceService,
+) {
+    @PostMapping("/start")
+    fun start(
+        @RequestBody request: StartRouteInstanceRequest,
+    ) = routeInstanceService.start(request)
+
+    @PatchMapping("/stop")
+    fun stop(
+        @RequestBody id: Long,
+    ) = routeInstanceService.stop(id)
+
+    @GetMapping("/{id}")
+    fun getById(
+        @PathVariable id: Long,
+    ) = this.routeInstanceService.getById(id)
+
+    @GetMapping("/station/{stationId}")
+    fun getForStation(
+        @PathVariable stationId: Long,
+    ) = routeInstanceService.getForStation(stationId)
+
+    @GetMapping()
+    fun getAll() = routeInstanceService.getAll()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/StationController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/StationController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/StationController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.service.StationService
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/stations")
+class StationController(
+    private val stationService: StationService,
+) {
+    @GetMapping()
+    fun getAllStations() = stationService.getAll()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/TicketController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/TicketController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/TicketController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,25 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.api.requests.TicketBuyRequest
+import mk.ukim.finki.busngobackend.api.responses.TicketResponse
+import mk.ukim.finki.busngobackend.service.BiletService
+import org.springframework.web.bind.annotation.*
+
+@RestController
+@RequestMapping("/api/tickets")
+class TicketController(
+    private val biletService: BiletService,
+) {
+    @GetMapping()
+    fun getTicketsByUser(): List<TicketResponse> = this.biletService.getTicketsByUser()
+
+    @PostMapping("/buy")
+    fun buyTicket(
+        @RequestBody request: TicketBuyRequest,
+    ): TicketResponse = this.biletService.buyTicket(request)
+
+    @PatchMapping("/activate/{id}")
+    fun activateTicket(
+        @PathVariable id: Long,
+    ): TicketResponse = this.biletService.activateTicket(id)
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/TicketTypeController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/TicketTypeController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/TicketTypeController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,16 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.domain.entities.Tipbilet
+import mk.ukim.finki.busngobackend.repository.TipbiletRepository
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/ticket-types")
+class TicketTypeController(
+    private val tipbiletRepository: TipbiletRepository,
+) {
+    @GetMapping()
+    fun getTicketTypes(): List<Tipbilet> = tipbiletRepository.findAll()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/UserController.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/UserController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/UserController.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,19 @@
+package mk.ukim.finki.busngobackend.api
+
+import mk.ukim.finki.busngobackend.api.responses.UserResponse
+import mk.ukim.finki.busngobackend.service.KorisnikService
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/users")
+class UserController(
+    private val korisnikService: KorisnikService,
+) {
+    @GetMapping()
+    fun getAuthenticatedUser(): UserResponse = korisnikService.getAuthenticatedUser()
+
+    @GetMapping("/passengers")
+    fun getAllPassengers() = korisnikService.getAllPassengers()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/AuthRequest.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/AuthRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/AuthRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.api.requests
+
+data class AuthRequest(
+    val email: String,
+    val password: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/FineRequest.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/FineRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/FineRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,12 @@
+package mk.ukim.finki.busngobackend.api.requests
+
+data class FineRequest(
+    var iznos: Double,
+    var plateno: Boolean,
+    var dokument: String,
+    val kontrolaId: Long,
+    var telefon: String?,
+    var ime: String?,
+    var adresa: String?,
+    var patnikId: Long?,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/RegisterRequest.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/RegisterRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/RegisterRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,10 @@
+package mk.ukim.finki.busngobackend.api.requests
+
+data class RegisterRequest(
+    val email: String,
+    val password: String,
+    val confirmPassword: String,
+    val name: String,
+    val address: String,
+    val phoneNumber: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/StartCommuteRequest.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/StartCommuteRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/StartCommuteRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,7 @@
+package mk.ukim.finki.busngobackend.api.requests
+
+data class StartCommuteRequest(
+    val ticketId: Long,
+    val routeInstanceId: Long,
+    val stationId: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/StartRouteInstanceRequest.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/StartRouteInstanceRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/StartRouteInstanceRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,7 @@
+package mk.ukim.finki.busngobackend.api.requests
+
+data class StartRouteInstanceRequest(
+    val lineId: Int,
+    val directionId: Long,
+    val busId: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/TicketBuyRequest.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/TicketBuyRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/requests/TicketBuyRequest.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,5 @@
+package mk.ukim.finki.busngobackend.api.requests
+
+data class TicketBuyRequest(
+    val type: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/AdminUsersResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/AdminUsersResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/AdminUsersResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,10 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+data class AdminUsersResponse(
+    val email: String,
+    val name: String,
+    val address: String,
+    val phoneNumber: String,
+    val id: Long,
+    val roles: List<String>,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/AuthResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/AuthResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/AuthResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,5 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+data class AuthResponse(
+    val token: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/CommuteResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/CommuteResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/CommuteResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,14 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+import mk.ukim.finki.busngobackend.domain.entities.PostojkaNaLinija
+import java.time.LocalDateTime
+
+data class CommuteResponse(
+    val commuter: UserResponse,
+    val ticket: TicketResponse,
+    val stationStart: PostojkaNaLinija,
+    val status: String,
+    val startDate: LocalDateTime,
+    val endDate: LocalDateTime?,
+    val id: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/ControlResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/ControlResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/ControlResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,10 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+import java.sql.Timestamp
+
+data class ControlResponse(
+    var id: Long,
+    val dateCreated: Timestamp,
+    val kondukter: UserResponse,
+    val instancaNaLinija: RouteInstanceResponse,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/FineResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/FineResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/FineResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+import java.sql.Timestamp
+
+data class FineResponse(
+    var id: Long,
+    var iznos: Double,
+    var plateno: Boolean,
+    val dateCreated: Timestamp,
+    var datePayed: Timestamp?,
+    var dokument: String,
+    val kondukter: UserResponse,
+    val kontrola: ControlResponse,
+    val patnik: UserResponse?,
+    var telefon: String?,
+    var ime: String?,
+    var adresa: String?,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/RouteInstanceResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/RouteInstanceResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/RouteInstanceResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,16 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+import mk.ukim.finki.busngobackend.domain.entities.Avtobus
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+import mk.ukim.finki.busngobackend.domain.entities.Pravec
+import java.time.LocalDateTime
+
+data class RouteInstanceResponse(
+    val id: Long,
+    val bus: Avtobus,
+    val direction: Pravec,
+    val line: Linija,
+    val driver: UserResponse,
+    val start: LocalDateTime,
+    val end: LocalDateTime?,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/TicketResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/TicketResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/TicketResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,12 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+import mk.ukim.finki.busngobackend.domain.entities.Tipbilet
+import java.time.LocalDateTime
+
+data class TicketResponse(
+    var id: Long,
+    var datumKupuvanje: LocalDateTime,
+    var datumAktivacija: LocalDateTime?,
+    var status: String,
+    var tip: Tipbilet,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/UserResponse.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/UserResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/api/responses/UserResponse.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.api.responses
+
+data class UserResponse(
+    val email: String,
+    val name: String,
+    val address: String,
+    val phoneNumber: String,
+    val id: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/ApplicationConfig.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/ApplicationConfig.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/ApplicationConfig.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,33 @@
+package mk.ukim.finki.busngobackend.config
+
+import mk.ukim.finki.busngobackend.encoder
+import mk.ukim.finki.busngobackend.repository.KorisnikRepository
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.security.authentication.AuthenticationManager
+import org.springframework.security.authentication.AuthenticationProvider
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
+import org.springframework.security.core.userdetails.UserDetailsService
+
+@Configuration
+class ApplicationConfig(
+    private val korisnikRepository: KorisnikRepository,
+) {
+    @Bean
+    fun userDetailsService(): UserDetailsService =
+        UserDetailsService { email ->
+            korisnikRepository.findByEmail(email)
+        }
+
+    @Bean
+    fun authenticationProvider(korisnikRepository: KorisnikRepository): AuthenticationProvider {
+        val provider = DaoAuthenticationProvider()
+        provider.setUserDetailsService(userDetailsService())
+        provider.setPasswordEncoder(encoder())
+        return provider
+    }
+
+    @Bean
+    fun authenticationManager(config: AuthenticationConfiguration): AuthenticationManager = config.authenticationManager
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/JwtAuthFilter.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/JwtAuthFilter.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/JwtAuthFilter.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,57 @@
+package mk.ukim.finki.busngobackend.config
+
+import jakarta.servlet.FilterChain
+import jakarta.servlet.http.HttpServletRequest
+import jakarta.servlet.http.HttpServletResponse
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.security.core.userdetails.UserDetails
+import org.springframework.security.core.userdetails.UserDetailsService
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
+import org.springframework.stereotype.Component
+import org.springframework.web.filter.OncePerRequestFilter
+
+@Component
+class JwtAuthFilter(
+    private val jwtService: JwtService,
+    private val userDetailsService: UserDetailsService,
+) : OncePerRequestFilter() {
+    override fun doFilterInternal(
+        request: HttpServletRequest,
+        response: HttpServletResponse,
+        filterChain: FilterChain,
+    ) {
+        val authHeader: String? = request.getHeader("Authorization")
+
+        if (authHeader == null || authHeader.doesNotContainBearer()) {
+            filterChain.doFilter(request, response)
+            return
+        }
+
+        val jwt = authHeader.extractTokenValue()
+        val email = jwtService.extractUsername(jwt)
+
+        if (email != null && SecurityContextHolder.getContext().authentication == null) {
+            val userDetails = this.userDetailsService.loadUserByUsername(email)
+
+            if (jwtService.isTokenValid(jwt, userDetails)) {
+                updateContext(userDetails, request)
+            }
+            filterChain.doFilter(request, response)
+        }
+    }
+
+    private fun updateContext(
+        userDetails: UserDetails,
+        request: HttpServletRequest,
+    ) {
+        val authToken = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
+        authToken.details = WebAuthenticationDetailsSource().buildDetails(request)
+
+        SecurityContextHolder.getContext().authentication = authToken
+    }
+
+    private fun String?.doesNotContainBearer(): Boolean = this == null || !this.startsWith("Bearer ")
+
+    private fun String?.extractTokenValue(): String = this!!.substringAfter("Bearer ")
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/JwtService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/JwtService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/JwtService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,64 @@
+package mk.ukim.finki.busngobackend.config
+
+import io.jsonwebtoken.Claims
+import io.jsonwebtoken.Jwts
+import io.jsonwebtoken.security.Keys
+import org.springframework.security.core.userdetails.UserDetails
+import org.springframework.stereotype.Service
+import java.security.Key
+import java.util.Date
+
+@Service
+class JwtService {
+    private val secretKey =
+        Keys.hmacShaKeyFor(
+            "hu55nfa3pRrBRV4DIlvKVDMrg7jnqla9".toByteArray(),
+        )
+
+    fun extractUsername(token: String): String? = extractClaim(token, Claims::getSubject)
+
+    fun <T> extractClaim(
+        token: String,
+        claimsResolver: (Claims) -> T,
+    ): T {
+        val claims = extractAllClaims(token)
+        return claimsResolver(claims)
+    }
+
+    fun generateToken(
+        extraClaims: Map<String, Any> = emptyMap(),
+        userDetails: UserDetails,
+    ): String =
+        Jwts
+            .builder()
+            .claims()
+            .subject(userDetails.username)
+            .issuedAt(Date(System.currentTimeMillis()))
+            .expiration(Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
+            .add(extraClaims)
+            .and()
+            .signWith(getSignInKey())
+            .compact()
+
+    fun isTokenValid(
+        token: String,
+        userDetails: UserDetails,
+    ): Boolean {
+        val username = extractUsername(token)
+        return username == userDetails.username && !isTokenExpired(token)
+    }
+
+    private fun isTokenExpired(token: String): Boolean = extractExpiration(token).before(Date())
+
+    private fun extractExpiration(token: String): Date = extractClaim(token, Claims::getExpiration)
+
+    private fun extractAllClaims(token: String): Claims =
+        Jwts
+            .parser()
+            .verifyWith(secretKey)
+            .build()
+            .parseSignedClaims(token)
+            .payload
+
+    private fun getSignInKey(): Key = secretKey
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/SecurityConfig.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/SecurityConfig.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/SecurityConfig.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,54 @@
+package mk.ukim.finki.busngobackend.config
+
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.http.HttpMethod
+import org.springframework.security.authentication.AuthenticationProvider
+import org.springframework.security.config.annotation.web.builders.HttpSecurity
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
+import org.springframework.security.config.http.SessionCreationPolicy
+import org.springframework.security.web.DefaultSecurityFilterChain
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
+
+@Configuration
+@EnableWebSecurity
+class SecurityConfig(
+    private val jwtAuthFilter: JwtAuthFilter,
+    private val authenticationProvider: AuthenticationProvider,
+) {
+    @Bean
+    fun securityFilterChain(
+        http: HttpSecurity,
+        jwtAuthFilter: JwtAuthFilter,
+    ): DefaultSecurityFilterChain =
+        http
+            .csrf {
+                it.disable()
+            }.authorizeHttpRequests {
+                it
+                    .requestMatchers("/api/booking/populate")
+                    .permitAll()
+                    .requestMatchers("/api/booking/**")
+                    .authenticated()
+                    .requestMatchers(HttpMethod.GET, "/api/city/**")
+                    .permitAll()
+                    .requestMatchers("/api/city/**")
+                    .authenticated()
+                    .requestMatchers(HttpMethod.POST, "/api/properties/**")
+                    .authenticated()
+                    .requestMatchers(HttpMethod.GET, "/api/properties/{id}/for-review")
+                    .authenticated()
+                    .requestMatchers(HttpMethod.POST, "/api/property-image/{id}/save-file")
+                    .permitAll()
+                    .requestMatchers(HttpMethod.POST, "/api/property-image/**")
+                    .authenticated()
+                    .requestMatchers(HttpMethod.POST, "/api/reviews/**")
+                    .authenticated()
+                    .anyRequest()
+                    .permitAll()
+            }.sessionManagement {
+                it.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+            }.authenticationProvider(authenticationProvider)
+            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter::class.java)
+            .build()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/WebSocketConfig.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/WebSocketConfig.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/config/WebSocketConfig.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.config
+
+import org.springframework.context.annotation.Configuration
+import org.springframework.messaging.simp.config.MessageBrokerRegistry
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
+import org.springframework.web.socket.config.annotation.StompEndpointRegistry
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer
+
+@Configuration
+@EnableWebSocketMessageBroker
+class WebSocketConfig : WebSocketMessageBrokerConfigurer {
+    override fun registerStompEndpoints(registry: StompEndpointRegistry) {
+        registry.addEndpoint("/ws").setAllowedOrigins("http://localhost:4200", "http://localhost:4200/").withSockJS()
+    }
+
+    override fun configureMessageBroker(registry: MessageBrokerRegistry) {
+        registry.setApplicationDestinationPrefixes("/app")
+        registry.enableSimpleBroker("/topic")
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Avtobus.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Avtobus.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Avtobus.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+
+@Entity
+data class Avtobus(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    var registracija: String,
+    var seriskiBroj: String,
+    var brojSedishta: Short?,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Bilet.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Bilet.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Bilet.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,19 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.enums.BiletEnum
+import java.sql.Timestamp
+
+@Entity
+data class Bilet(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    var datumKupuvanje: Timestamp,
+    var datumAktivacija: Timestamp?,
+    @Enumerated(EnumType.STRING)
+    var status: BiletEnum,
+    @ManyToOne
+    var patnik: Patnik,
+    @ManyToOne
+    var tip: Tipbilet,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/InstancaNaLinija.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/InstancaNaLinija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/InstancaNaLinija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+import java.sql.Timestamp
+
+@Entity
+data class InstancaNaLinija(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Long,
+    var startDate: Timestamp,
+    var endDate: Timestamp?,
+    @ManyToOne
+    var vozac: Vozac,
+    @ManyToOne
+    var avtobus: Avtobus,
+    @ManyToOne
+    var linija: Linija,
+    @ManyToOne
+    var pravec: Pravec,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/InstancaNaLinijaPostojkaNaLinija.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/InstancaNaLinijaPostojkaNaLinija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/InstancaNaLinijaPostojkaNaLinija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.ManyToOne
+import java.sql.Timestamp
+
+@Entity
+data class InstancaNaLinijaPostojkaNaLinija(
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @ManyToOne
+    var postojkaNaLinija: PostojkaNaLinija,
+    @ManyToOne
+    var instancaNaLinija: InstancaNaLinija,
+    var timestamp: Timestamp,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kazna.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kazna.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kazna.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,19 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+import java.sql.Timestamp
+
+@Entity
+data class Kazna(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Long,
+    var iznos: Double,
+    var plateno: Boolean,
+    val dateCreated: Timestamp,
+    var datePayed: Timestamp?,
+    var dokument: String,
+    @ManyToOne
+    val kondukter: Kondukter,
+    @ManyToOne
+    val kontrola: Kontrola,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KaznaZaNeregistriran.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KaznaZaNeregistriran.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KaznaZaNeregistriran.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,14 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+
+@Entity
+data class KaznaZaNeregistriran(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @OneToOne
+    val kazna: Kazna,
+    var telefon: String,
+    var ime: String,
+    var adresa: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KaznaZaRegistriran.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KaznaZaRegistriran.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KaznaZaRegistriran.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,13 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+
+@Entity
+data class KaznaZaRegistriran(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @OneToOne
+    val kazna: Kazna,
+    @ManyToOne
+    val patnik: Patnik,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kondukter.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kondukter.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kondukter.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,12 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+
+@Entity
+data class Kondukter(
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @OneToOne
+    var vraboten: Vraboten,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kontrola.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kontrola.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Kontrola.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+import java.sql.Timestamp
+
+@Entity
+data class Kontrola(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Long,
+    val dateCreated: Timestamp,
+    @ManyToOne
+    val kondukter: Kondukter,
+    @ManyToOne
+    val instancaNaLinija: InstancaNaLinija,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Korisnik.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Korisnik.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Korisnik.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,38 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+import org.springframework.security.core.GrantedAuthority
+import org.springframework.security.core.userdetails.UserDetails
+
+@Entity
+class Korisnik(
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    val ime: String,
+    val adresa: String,
+    val telefon: String,
+    var email: String,
+    @Column(name = "is_admin")
+    var admin: Boolean,
+    var lozinka: String,
+    @OneToMany(fetch = FetchType.EAGER, mappedBy = "korisnik")
+    var roles: List<KorisnikRole>?,
+) : UserDetails {
+    constructor() : this(0, "", "", "", "", false, "", emptyList()) {
+    }
+
+    override fun getAuthorities(): MutableCollection<out GrantedAuthority> = roles?.map { it.role!! }?.toMutableList() ?: mutableListOf()
+
+    override fun getPassword(): String = lozinka
+
+    override fun getUsername(): String = email
+
+    override fun isAccountNonExpired(): Boolean = true
+
+    override fun isAccountNonLocked(): Boolean = true
+
+    override fun isCredentialsNonExpired(): Boolean = true
+
+    override fun isEnabled(): Boolean = true
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KorisnikRole.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KorisnikRole.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/KorisnikRole.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.ManyToOne
+
+@Entity
+data class KorisnikRole(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @ManyToOne
+    val korisnik: Korisnik?,
+    @ManyToOne
+    val role: Role?,
+) {
+    constructor() : this(0, null, null) {
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Linija.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Linija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Linija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,13 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+
+@Entity
+data class Linija(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Int,
+    var ime: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/LinijaPravec.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/LinijaPravec.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/LinijaPravec.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,17 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.ManyToOne
+
+@Entity
+data class LinijaPravec(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @ManyToOne
+    val linija: Linija,
+    @ManyToOne
+    val pravec: Pravec,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Patnik.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Patnik.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Patnik.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,11 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+
+@Entity
+data class Patnik(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @OneToOne(fetch = FetchType.EAGER)
+    var korisnik: Korisnik,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Postojka.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Postojka.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Postojka.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,16 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+
+@Entity
+data class Postojka(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Int,
+    var ime: String,
+    var lat: Double,
+    var lon: Double,
+    var opis: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/PostojkaNaLinija.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/PostojkaNaLinija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/PostojkaNaLinija.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.ManyToOne
+
+@Entity
+data class PostojkaNaLinija(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Long,
+    var redenBroj: Short,
+    @ManyToOne
+    val linija: Linija,
+    @ManyToOne
+    val postojka: Postojka,
+    @ManyToOne
+    val pravec: Pravec,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Pravec.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Pravec.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Pravec.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,14 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+
+@Entity
+data class Pravec(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    var pravec: String,
+    var opis: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Role.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Role.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Role.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import org.springframework.security.core.GrantedAuthority
+
+@Entity
+class Role : GrantedAuthority {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long = 0
+    var name: String = ""
+    var description: String = ""
+
+    override fun getAuthority(): String = name
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/SeSimnuvaNa.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/SeSimnuvaNa.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/SeSimnuvaNa.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.OneToOne
+
+@Entity
+data class SeSimnuvaNa(
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @OneToOne
+    val vozenje: Vozenje,
+    @OneToOne
+    val postojkaNaLinija: PostojkaNaLinija,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Tipbilet.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Tipbilet.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Tipbilet.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+
+@Entity
+data class Tipbilet(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Long,
+    var trajnost: Long,
+    var cena: Float,
+    var ime: String,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vozac.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vozac.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vozac.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import jakarta.persistence.OneToOne
+
+@Entity
+data class Vozac(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @OneToOne
+    var vraboten: Vraboten,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vozenje.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vozenje.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vozenje.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,23 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.enums.VozenjeStatus
+import java.sql.Timestamp
+
+@Entity
+data class Vozenje(
+    @GeneratedValue(strategy = GenerationType.IDENTITY) @Id
+    var id: Long,
+    var startDate: Timestamp,
+    var endDate: Timestamp?,
+    @Enumerated(EnumType.STRING)
+    var status: VozenjeStatus,
+    @ManyToOne
+    var patnik: Patnik,
+    @ManyToOne
+    var postojkaNaLinijaStart: PostojkaNaLinija,
+    @ManyToOne
+    var instancaNaLinija: InstancaNaLinija,
+    @ManyToOne
+    var bilet: Bilet,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vraboten.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vraboten.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/entities/Vraboten.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,19 @@
+package mk.ukim.finki.busngobackend.domain.entities
+
+import jakarta.persistence.Entity
+import jakarta.persistence.FetchType
+import jakarta.persistence.GeneratedValue
+import jakarta.persistence.GenerationType
+import jakarta.persistence.Id
+import java.sql.Date
+
+@Entity
+data class Vraboten(
+    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+    var id: Long,
+    @jakarta.persistence.OneToOne(fetch = FetchType.EAGER)
+    var korisnik: Korisnik,
+    var plata: Double,
+    val datumNaVrabotuvanje: Date,
+    var datumPrekinVrabotuvanje: Date?,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/BiletEnum.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/BiletEnum.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/BiletEnum.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,7 @@
+package mk.ukim.finki.busngobackend.domain.enums
+
+enum class BiletEnum {
+    INACTIVE,
+    ACTIVE,
+    EXPIRED,
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/RoleEnum.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/RoleEnum.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/RoleEnum.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,10 @@
+package mk.ukim.finki.busngobackend.domain.enums
+
+enum class RoleEnum {
+    ROLE_ADMIN,
+    ROLE_DRIVER,
+    ROLE_CONDUCTOR,
+    ROLE_PASSENGER,
+}
+
+fun RoleEnum.toId(): Long = this.ordinal + 1L
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/VozenjeStatus.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/VozenjeStatus.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/enums/VozenjeStatus.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.domain.enums
+
+enum class VozenjeStatus {
+    ACTIVE,
+    FINISHED,
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/helpers/RouteInstanceOnStation.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/helpers/RouteInstanceOnStation.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/helpers/RouteInstanceOnStation.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,11 @@
+package mk.ukim.finki.busngobackend.domain.helpers
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import mk.ukim.finki.busngobackend.domain.entities.PostojkaNaLinija
+import java.sql.Timestamp
+
+data class RouteInstanceOnStation(
+    val instance: InstancaNaLinija,
+    val station: PostojkaNaLinija,
+    val timestamp: Timestamp,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/AverageTimeBetweenStations.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/AverageTimeBetweenStations.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/AverageTimeBetweenStations.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.entities.PostojkaNaLinija
+
+@Entity
+@Table(name = "avg_time_diffs")
+data class AverageTimeBetweenStations(
+    @Column(name = "id")
+    @Id
+    val id: Long,
+    @ManyToOne
+    @JoinColumn(name = "start_station_id")
+    val startStation: PostojkaNaLinija,
+    @ManyToOne
+    @JoinColumn(name = "end_station_id")
+    val endStation: PostojkaNaLinija,
+    @Column(name = "avg_time_diff_seconds")
+    val timeInSeconds: Double,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/CommutesByHour.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/CommutesByHour.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/CommutesByHour.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+
+@Entity
+@Table(name = "most_busy_part_of_the_day")
+data class CommutesByHour(
+    @Id
+    val id: Long,
+    @ManyToOne
+    @JoinColumn(name = "linija_id")
+    val line: Linija,
+    @Column(name = "interval_1h")
+    val interval: String,
+    @Column(name = "broj_pati")
+    val numberOfCommutes: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/CommutesByLine.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/CommutesByLine.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/CommutesByLine.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,16 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+
+@Entity
+@Table(name = "commutes_by_line")
+data class CommutesByLine(
+    @Id
+    val id: Long,
+    @ManyToOne
+    @JoinColumn(name = "linija_id")
+    val line: Linija,
+    @Column(name = "count")
+    val commutesPerLine: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/FinesByLine.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/FinesByLine.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/FinesByLine.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,16 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+
+@Entity
+@Table(name = "kazna_po_linija")
+data class FinesByLine(
+    @Id
+    val id: Long,
+    @JoinColumn(name = "line_id")
+    @ManyToOne
+    val line: Linija,
+    @Column(name = "count")
+    val count: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/NumberOfPassengersByLineAndStation.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/NumberOfPassengersByLineAndStation.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/NumberOfPassengersByLineAndStation.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,20 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+import mk.ukim.finki.busngobackend.domain.entities.Postojka
+
+@Entity
+@Table(name = "number_passengers_per_line_and_station")
+data class NumberOfPassengersByLineAndStation(
+    @Id
+    val id: Long,
+    @ManyToOne
+    @JoinColumn(name = "line_id")
+    val line: Linija,
+    @ManyToOne
+    @JoinColumn(name = "station_id")
+    val station: Postojka,
+    @Column(name = "count")
+    val passengersByLineAndStation: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/TicketSales.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/TicketSales.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/TicketSales.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.*
+import mk.ukim.finki.busngobackend.domain.entities.Tipbilet
+
+@Entity
+@Table(name = "ticket_sales")
+data class TicketSales(
+    @Id
+    val id: Long,
+    @ManyToOne
+    @JoinColumn(name = "tip_id")
+    val type: Tipbilet,
+    @Column(name = "interval_1h")
+    val interval: String,
+    @Column(name = "broj_pati")
+    val numberOfSales: Long,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/TotalIncome.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/TotalIncome.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/domain/views/TotalIncome.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,21 @@
+package mk.ukim.finki.busngobackend.domain.views
+
+import jakarta.persistence.Column
+import jakarta.persistence.Entity
+import jakarta.persistence.Id
+import jakarta.persistence.Table
+
+@Entity
+@Table(name = "total_income")
+class TotalIncome(
+    @Id
+    val id: Long,
+    @Column(name = "year")
+    val year: String,
+    @Column(name = "fines_income")
+    val finesIncome: Double,
+    @Column(name = "ticket_income")
+    val ticketIncome: Double,
+    @Column(name = "total_income")
+    val totalIncome: Double,
+)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/RouteInstanceOnStationEvent.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/RouteInstanceOnStationEvent.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/RouteInstanceOnStationEvent.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,8 @@
+package mk.ukim.finki.busngobackend.events
+
+import mk.ukim.finki.busngobackend.domain.helpers.RouteInstanceOnStation
+import org.springframework.context.ApplicationEvent
+
+class RouteInstanceOnStationEvent(
+    source: RouteInstanceOnStation,
+) : ApplicationEvent(source)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/StartRouteEvent.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/StartRouteEvent.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/StartRouteEvent.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,8 @@
+package mk.ukim.finki.busngobackend.events
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import org.springframework.context.ApplicationEvent
+
+class StartRouteEvent(
+    source: InstancaNaLinija,
+) : ApplicationEvent(source)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/StopRouteInstanceEvent.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/StopRouteInstanceEvent.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/events/StopRouteInstanceEvent.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,8 @@
+package mk.ukim.finki.busngobackend.events
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import org.springframework.context.ApplicationEvent
+
+class StopRouteInstanceEvent(
+    source: InstancaNaLinija,
+) : ApplicationEvent(source)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/listener/RouteEventListener.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/listener/RouteEventListener.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/listener/RouteEventListener.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,56 @@
+package mk.ukim.finki.busngobackend.listener
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import mk.ukim.finki.busngobackend.domain.helpers.RouteInstanceOnStation
+import mk.ukim.finki.busngobackend.events.RouteInstanceOnStationEvent
+import mk.ukim.finki.busngobackend.events.StartRouteEvent
+import mk.ukim.finki.busngobackend.events.StopRouteInstanceEvent
+import mk.ukim.finki.busngobackend.service.RouteInstanceOnStationService
+import mk.ukim.finki.busngobackend.service.RouteInstanceService
+import mk.ukim.finki.busngobackend.service.StationService
+import mk.ukim.finki.busngobackend.service.WebSocketService
+import mk.ukim.finki.busngobackend.simulator.RouteInstanceSimulator
+import org.springframework.context.ApplicationEventPublisher
+import org.springframework.context.event.EventListener
+import org.springframework.scheduling.annotation.Async
+import org.springframework.stereotype.Component
+
+@Component
+class RouteEventListener(
+    private val stationService: StationService,
+    private val simulator: RouteInstanceSimulator,
+    private val eventPublisher: ApplicationEventPublisher,
+    private val routeInstanceService: RouteInstanceService,
+    private val routeInstanceOnStationService: RouteInstanceOnStationService,
+    private val webSocketService: WebSocketService,
+) {
+    @Async
+    @EventListener
+    fun startRouteEvent(event: StartRouteEvent) {
+        println(event)
+        println(event)
+        val instance = event.source as InstancaNaLinija
+        val line = instance.linija
+        val direction = instance.pravec
+        val stations = stationService.findStationsByLineIdAndDirectionId(line.id, direction.id)
+
+        simulator.simulate(instance, stations)
+    }
+
+    @Async
+    @EventListener
+    fun routeInstanceOnStation(event: RouteInstanceOnStationEvent) {
+        println("------------------------------------------------")
+        println(event)
+        val source = event.source as RouteInstanceOnStation
+        routeInstanceOnStationService.create(source.instance.id, source.station.id, source.timestamp)
+        // todo: publish event to the websocket so that the user gets notified
+        webSocketService.sendMessage("routes", "Updated routes")
+    }
+
+    @EventListener
+    fun stopRouteEvent(event: StopRouteInstanceEvent) {
+        val instance = event.source as InstancaNaLinija
+        routeInstanceService.stop(instance.id)
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/listener/WebSocketEventListener.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/listener/WebSocketEventListener.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/listener/WebSocketEventListener.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.listener
+
+import org.springframework.context.event.EventListener
+import org.springframework.messaging.simp.stomp.StompHeaderAccessor
+import org.springframework.stereotype.Component
+import org.springframework.web.socket.messaging.SessionDisconnectEvent
+
+@Component
+class WebSocketEventListener {
+    @EventListener
+    fun handleWebSocketDisconnectListener(event: SessionDisconnectEvent) {
+        val headerAccessor = StompHeaderAccessor.wrap(event.message)
+        val username = headerAccessor.sessionAttributes?.get("username")
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/mapper/ClassToDtoMapper.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/mapper/ClassToDtoMapper.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/mapper/ClassToDtoMapper.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,85 @@
+package mk.ukim.finki.busngobackend.mapper
+
+import mk.ukim.finki.busngobackend.api.responses.*
+import mk.ukim.finki.busngobackend.domain.entities.*
+import org.springframework.stereotype.Service
+
+@Service
+class ClassToDtoMapper {
+    fun toUserResponse(user: Korisnik): UserResponse =
+        UserResponse(
+            id = user.id,
+            email = user.email,
+            phoneNumber = user.telefon,
+            address = user.adresa,
+            name = user.ime,
+        )
+
+    fun toTicketResponse(it: Bilet) =
+        TicketResponse(
+            id = it.id,
+            tip = it.tip,
+            datumKupuvanje = it.datumKupuvanje.toLocalDateTime(),
+            status = it.status.name,
+            datumAktivacija = it.datumAktivacija?.toLocalDateTime(),
+        )
+
+    fun toRouteInstanceResponse(it: InstancaNaLinija) =
+        RouteInstanceResponse(
+            line = it.linija,
+            bus = it.avtobus,
+            start = it.startDate.toLocalDateTime(),
+            driver = toUserResponse(it.vozac.vraboten.korisnik),
+            direction = it.pravec,
+            end = it.endDate?.toLocalDateTime(),
+            id = it.id,
+        )
+
+    fun toCommuteResponse(it: Vozenje) =
+        CommuteResponse(
+            status = it.status.name,
+            endDate = it.endDate?.toLocalDateTime(),
+            startDate = it.startDate.toLocalDateTime(),
+            commuter = this.toUserResponse(it.patnik.korisnik),
+            stationStart = it.postojkaNaLinijaStart,
+            ticket = this.toTicketResponse(it.bilet),
+            id = it.id,
+        )
+
+    fun toControlResponse(kontrola: Kontrola) =
+        ControlResponse(
+            id = kontrola.id,
+            instancaNaLinija = this.toRouteInstanceResponse(kontrola.instancaNaLinija),
+            kondukter = this.toUserResponse(kontrola.kondukter.vraboten.korisnik),
+            dateCreated = kontrola.dateCreated,
+        )
+
+    fun toFineResponse(
+        kazna: Kazna,
+        kzr: KaznaZaRegistriran?,
+        kzn: KaznaZaNeregistriran?,
+    ) = FineResponse(
+        dokument = kazna.dokument,
+        kontrola = this.toControlResponse(kazna.kontrola),
+        plateno = kazna.plateno,
+        iznos = kazna.iznos,
+        id = kazna.id,
+        kondukter = this.toUserResponse(kazna.kondukter.vraboten.korisnik),
+        datePayed = kazna.datePayed,
+        dateCreated = kazna.dateCreated,
+        adresa = kzn?.adresa,
+        patnik = kzr?.patnik?.let { this.toUserResponse(it.korisnik) },
+        ime = kzn?.ime,
+        telefon = kzn?.telefon,
+    )
+
+    fun toAdminUsersResponse(user: Korisnik): AdminUsersResponse =
+        AdminUsersResponse(
+            id = user.id,
+            email = user.email,
+            phoneNumber = user.telefon,
+            address = user.adresa,
+            name = user.ime,
+            roles = user.roles!!.map { it.role!!.name },
+        )
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/AvgTimeDIffsRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/AvgTimeDIffsRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/AvgTimeDIffsRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.AverageTimeBetweenStations
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface AvgTimeDIffsRepository : JpaRepository<AverageTimeBetweenStations, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/AvtobusRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/AvtobusRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/AvtobusRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,21 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Avtobus
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.data.jpa.repository.Query
+
+interface AvtobusRepository : JpaRepository<Avtobus, Long> {
+    @Query(
+        nativeQuery = true,
+        value =
+            "select a.id, a.registracija, a.seriski_broj, a.broj_sedishta " +
+                "from project.avtobus a " +
+                "where not exists( " +
+                "select 1 " +
+                "from project.avtobus a1 " +
+                "join project.instanca_na_linija inl on inl.avtobus_id = a1.id " +
+                "where a1.id = a.id and " +
+                "inl.end_date is null)",
+    )
+    fun findAllFreeBuses(): List<Avtobus>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/BiletRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/BiletRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/BiletRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,14 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Bilet
+import mk.ukim.finki.busngobackend.domain.entities.Patnik
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface BiletRepository : JpaRepository<Bilet, Long> {
+    fun findAllByPatnik(patnik: Patnik): List<Bilet>
+
+    fun findByIdAndPatnik(
+        id: Long,
+        patnik: Patnik,
+    ): Bilet?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/CommutesByHourRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/CommutesByHourRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/CommutesByHourRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.CommutesByHour
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface CommutesByHourRepository : JpaRepository<CommutesByHour, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/CommutesByLineRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/CommutesByLineRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/CommutesByLineRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.CommutesByLine
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface CommutesByLineRepository : JpaRepository<CommutesByLine, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/FinesByLineRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/FinesByLineRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/FinesByLineRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.FinesByLine
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface FinesByLineRepository : JpaRepository<FinesByLine, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/InstancaNaLinijaPostojkaNaLinijaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/InstancaNaLinijaPostojkaNaLinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/InstancaNaLinijaPostojkaNaLinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,21 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinijaPostojkaNaLinija
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.data.jpa.repository.Query
+import java.sql.Timestamp
+
+interface InstancaNaLinijaPostojkaNaLinijaRepository : JpaRepository<InstancaNaLinijaPostojkaNaLinija, Long> {
+    @Query(
+        nativeQuery = true,
+        value = """
+            select id, instanca_na_linija_id, postojka_na_linija_id, timestamp from project.instanca_na_linija_postojka_na_linija where id = (
+            select id from project.instanca_na_linija_postojka_na_linija where instanca_na_linija_id = ?1 order by EXTRACT(epoch FROM (timestamp - ?2)) limit 1
+            )
+        """,
+    )
+    fun findByInstancaNaLinijaAndTimestampNearestTo(
+        instancaNaLinija: Long,
+        startDate: Timestamp,
+    ): InstancaNaLinijaPostojkaNaLinija?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/InstancaNaLinijaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/InstancaNaLinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/InstancaNaLinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,38 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.data.jpa.repository.Query
+
+interface InstancaNaLinijaRepository : JpaRepository<InstancaNaLinija, Long> {
+    @Query(
+        value = "select count(id) > 0 from project.instanca_na_linija inl where inl.vozac_id=:vozac and inl.end_date is null",
+        nativeQuery = true,
+    )
+    fun existsByVozacAndEndDateIsNull(vozac: Long): Boolean
+
+    @Query(
+        value =
+            """
+            select distinct inl.id
+from project.instanca_na_linija inl
+         join project.instanca_na_linija_postojka_na_linija inlpnl on inl.id = inlpnl.instanca_na_linija_id
+where end_date is null
+  and linija_id in (
+    select distinct(pnl.linija_id)
+    from project.postojka_na_linija pnl
+    where postojka_id = ?1
+)
+except
+select inl.id
+from project.postojka_na_linija pnl
+         join project.instanca_na_linija inl on inl.linija_id = pnl.linija_id and inl.pravec_id = pnl.pravec_id
+join project.instanca_na_linija_postojka_na_linija inlpnl on inl.id = inlpnl.instanca_na_linija_id and pnl.id = inlpnl.postojka_na_linija_id
+where inl.end_date is null and postojka_id = ?1;
+        """,
+        nativeQuery = true,
+    )
+    fun findIncomingRouteInstancesForStation(stationId: Int): List<Long>
+
+    fun findAllByEndDateIsNull(): List<InstancaNaLinija>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Kazna
+import mk.ukim.finki.busngobackend.domain.entities.Kontrola
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KaznaRepository : JpaRepository<Kazna, Long> {
+    fun findAllByKontrola(kontrola: Kontrola): List<Kazna>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaZaNeregistriranRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaZaNeregistriranRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaZaNeregistriranRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Kazna
+import mk.ukim.finki.busngobackend.domain.entities.KaznaZaNeregistriran
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KaznaZaNeregistriranRepository : JpaRepository<KaznaZaNeregistriran, Long> {
+    fun findAllByKaznaIn(kazni: List<Kazna>): List<KaznaZaNeregistriran>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaZaRegistriranRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaZaRegistriranRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KaznaZaRegistriranRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Kazna
+import mk.ukim.finki.busngobackend.domain.entities.KaznaZaRegistriran
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KaznaZaRegistriranRepository : JpaRepository<KaznaZaRegistriran, Long> {
+    fun findAllByKaznaIn(kazni: List<Kazna>): List<KaznaZaRegistriran>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KondukterRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KondukterRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KondukterRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Kondukter
+import mk.ukim.finki.busngobackend.domain.entities.Vraboten
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KondukterRepository : JpaRepository<Kondukter, Long> {
+    fun findByVraboten(vraboten: Vraboten): Kondukter?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KontrolaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KontrolaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KontrolaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Kondukter
+import mk.ukim.finki.busngobackend.domain.entities.Kontrola
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KontrolaRepository : JpaRepository<Kontrola, Long> {
+    fun findAllByKondukterOrderByDateCreatedDesc(kondukter: Kondukter): List<Kontrola>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KorisnikRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KorisnikRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KorisnikRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,8 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Korisnik
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KorisnikRepository : JpaRepository<Korisnik, Long> {
+    fun findByEmail(email: String): Korisnik?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KorisnikRoleRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KorisnikRoleRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/KorisnikRoleRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Korisnik
+import mk.ukim.finki.busngobackend.domain.entities.KorisnikRole
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface KorisnikRoleRepository : JpaRepository<KorisnikRole, Long> {
+    fun findAllByKorisnik(user: Korisnik): List<KorisnikRole>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/LinijaPravecRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/LinijaPravecRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/LinijaPravecRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,15 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+import mk.ukim.finki.busngobackend.domain.entities.LinijaPravec
+import mk.ukim.finki.busngobackend.domain.entities.Pravec
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface LinijaPravecRepository : JpaRepository<LinijaPravec, Long> {
+    fun findAllByLinija(linija: Linija): List<LinijaPravec>
+
+    fun existsByLinijaAndPravec(
+        linija: Linija,
+        pravec: Pravec,
+    ): Boolean
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/LinijaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/LinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/LinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface LinijaRepository : JpaRepository<Linija, Int>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/NumberOfPassengersByLineAndStationRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/NumberOfPassengersByLineAndStationRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/NumberOfPassengersByLineAndStationRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.NumberOfPassengersByLineAndStation
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface NumberOfPassengersByLineAndStationRepository : JpaRepository<NumberOfPassengersByLineAndStation, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PatnikRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PatnikRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PatnikRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Korisnik
+import mk.ukim.finki.busngobackend.domain.entities.Patnik
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface PatnikRepository : JpaRepository<Patnik, Long> {
+    fun findByKorisnik(korisnik: Korisnik): Patnik?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PostojkaNaLinijaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PostojkaNaLinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PostojkaNaLinijaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,42 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+import mk.ukim.finki.busngobackend.domain.entities.Postojka
+import mk.ukim.finki.busngobackend.domain.entities.PostojkaNaLinija
+import mk.ukim.finki.busngobackend.domain.entities.Pravec
+import mk.ukim.finki.busngobackend.domain.views.AverageTimeBetweenStations
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.data.jpa.repository.Query
+
+interface PostojkaNaLinijaRepository : JpaRepository<PostojkaNaLinija, Long> {
+    fun findByLinija(linija: Linija): List<PostojkaNaLinija>
+
+    fun findByLinijaAndPravec(
+        linija: Linija,
+        pravec: Pravec,
+    ): List<PostojkaNaLinija>
+
+    fun existsByLinijaAndPostojka(
+        linija: Linija,
+        postojkaStart: Postojka,
+    ): Boolean
+
+    fun findByLinijaAndPostojka(
+        linija: Linija,
+        postojkaStart: Postojka,
+    ): PostojkaNaLinija?
+
+    fun findByLinijaAndPostojkaAndPravec(
+        linija: Linija,
+        postojkaStart: Postojka,
+        pravec: Pravec,
+    ): PostojkaNaLinija?
+
+    @Query(
+        nativeQuery = true,
+        value = """
+            select id, start_station_id, end_station_id, avg_time_diff_seconds from project.avg_time_diffs
+        """,
+    )
+    fun getAverageTimeBetweenStations(): List<AverageTimeBetweenStations>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PostojkaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PostojkaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PostojkaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Postojka
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface PostojkaRepository : JpaRepository<Postojka, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PravecRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PravecRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/PravecRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Pravec
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface PravecRepository : JpaRepository<Pravec, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/RoleRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/RoleRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/RoleRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,8 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Role
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface RoleRepository : JpaRepository<Role, Long> {
+    fun findAllByNameLikeIgnoreCase(name: String): List<Role>
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/SeSimnuvaNaRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/SeSimnuvaNaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/SeSimnuvaNaRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.SeSimnuvaNa
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface SeSimnuvaNaRepository : JpaRepository<SeSimnuvaNa, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TicketSalesRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TicketSalesRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TicketSalesRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.TicketSales
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface TicketSalesRepository : JpaRepository<TicketSales, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TipbiletRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TipbiletRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TipbiletRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Tipbilet
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface TipbiletRepository : JpaRepository<Tipbilet, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TotalIncomeRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TotalIncomeRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/TotalIncomeRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.views.TotalIncome
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface TotalIncomeRepository : JpaRepository<TotalIncome, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VozacRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VozacRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VozacRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Vozac
+import mk.ukim.finki.busngobackend.domain.entities.Vraboten
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface VozacRepository : JpaRepository<Vozac, Long> {
+    fun findByVraboten(vraboten: Vraboten): Vozac?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VozenjeRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VozenjeRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VozenjeRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,6 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Vozenje
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface VozenjeRepository : JpaRepository<Vozenje, Long>
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VrabotenRepository.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VrabotenRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/repository/VrabotenRepository.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,9 @@
+package mk.ukim.finki.busngobackend.repository
+
+import mk.ukim.finki.busngobackend.domain.entities.Korisnik
+import mk.ukim.finki.busngobackend.domain.entities.Vraboten
+import org.springframework.data.jpa.repository.JpaRepository
+
+interface VrabotenRepository : JpaRepository<Vraboten, Long> {
+    fun findByKorisnik(korisnik: Korisnik): Vraboten?
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/AdminService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/AdminService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/AdminService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,91 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.api.responses.AdminUsersResponse
+import mk.ukim.finki.busngobackend.domain.entities.KorisnikRole
+import mk.ukim.finki.busngobackend.domain.enums.RoleEnum
+import mk.ukim.finki.busngobackend.domain.views.*
+import mk.ukim.finki.busngobackend.repository.*
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+
+@Service
+class AdminService(
+    private val avgTimeDIffsRepository: AvgTimeDIffsRepository,
+    private val finesByLineRepository: FinesByLineRepository,
+    private val commutesByHourRepository: CommutesByHourRepository,
+    private val commutesByLineRepository: CommutesByLineRepository,
+    private val numberOfPassengersByLineAndStationRepository: NumberOfPassengersByLineAndStationRepository,
+    private val ticketSalesRepository: TicketSalesRepository,
+    private val totalIncomeRepository: TotalIncomeRepository,
+    private val korisnikService: KorisnikService,
+    private val korisnikRepository: KorisnikRepository,
+    private val roleRepository: RoleRepository,
+    private val korisnikRoleRepository: KorisnikRoleRepository,
+    private val authService: AuthService,
+) {
+    fun getAverageTimeBetweenStations(): List<AverageTimeBetweenStations> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return avgTimeDIffsRepository.findAll()
+    }
+
+    fun getFinesByLine(): List<FinesByLine> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return finesByLineRepository.findAll()
+    }
+
+    fun getCommutesByHour(): List<CommutesByHour> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return commutesByHourRepository.findAll()
+    }
+
+    fun getCommutesByLine(): List<CommutesByLine> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return commutesByLineRepository.findAll()
+    }
+
+    fun getNumberOfPassengersByLineAndStation(): List<NumberOfPassengersByLineAndStation> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return numberOfPassengersByLineAndStationRepository.findAll()
+    }
+
+    fun getTicketSales(): List<TicketSales> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return ticketSalesRepository.findAll()
+    }
+
+    fun getTotalIncome(): List<TotalIncome> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return totalIncomeRepository.findAll()
+    }
+
+    fun getAllUsers(): List<AdminUsersResponse> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        return korisnikService.getAllUsers()
+    }
+
+    fun updateRolesForUser(
+        id: Long,
+        roleNames: List<String>,
+    ): List<AdminUsersResponse> {
+        authService.hasAuthority(RoleEnum.ROLE_ADMIN)
+        val user = korisnikRepository.findByIdOrNull(id) ?: throw NotFoundException("User not found")
+        val roles = roleNames.flatMap { role -> roleRepository.findAllByNameLikeIgnoreCase(role) }
+
+        val allByKorisnik = korisnikRoleRepository.findAllByKorisnik(user)
+
+        val rolesToDelete = allByKorisnik.filter { it.role !in roles }
+        val rolesToAdd =
+            roles.filter { it !in allByKorisnik.map { r -> r.role } }.map {
+                KorisnikRole(
+                    id = 0L,
+                    korisnik = user,
+                    role = it,
+                )
+            }
+
+        korisnikRoleRepository.deleteAll(rolesToDelete)
+        korisnikRoleRepository.saveAll(rolesToAdd)
+        return getAllUsers()
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/AuthService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/AuthService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/AuthService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,157 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.api.requests.AuthRequest
+import mk.ukim.finki.busngobackend.api.requests.RegisterRequest
+import mk.ukim.finki.busngobackend.api.responses.AuthResponse
+import mk.ukim.finki.busngobackend.config.JwtService
+import mk.ukim.finki.busngobackend.domain.entities.*
+import mk.ukim.finki.busngobackend.domain.enums.RoleEnum
+import mk.ukim.finki.busngobackend.domain.enums.toId
+import mk.ukim.finki.busngobackend.repository.*
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import mk.ukim.finki.busngobackend.service.exceptions.UnauthorizedAccessException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.security.authentication.AuthenticationManager
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
+import org.springframework.security.core.GrantedAuthority
+import org.springframework.security.core.context.SecurityContext
+import org.springframework.security.core.context.SecurityContextHolder
+import org.springframework.security.core.userdetails.UserDetailsService
+import org.springframework.stereotype.Service
+
+@Service
+class AuthService(
+    private val authenticationManager: AuthenticationManager,
+    private val userDetailsService: UserDetailsService,
+    private val jwtService: JwtService,
+    private val korisnikRepository: KorisnikRepository,
+    private val korisnikRoleRepository: KorisnikRoleRepository,
+    private val roleRepository: RoleRepository,
+    private val instancaNaLinijaRepository: InstancaNaLinijaRepository,
+    private val vrabotenRepository: VrabotenRepository,
+    private val vozacRepository: VozacRepository,
+    private val kondukterRepository: KondukterRepository,
+    private val patnikRepository: PatnikRepository,
+) {
+    fun getSecurityContext(): SecurityContext = SecurityContextHolder.getContext()
+
+    fun getAuthenticatedUser(): Korisnik = userDetailsService.loadUserByUsername(getSecurityContext().authentication.name) as Korisnik
+
+    fun hasAuthority(authority: RoleEnum): Boolean =
+        getAuthenticatedUser().authorities.contains(roleRepository.findByIdOrNull(authority.toId()) as GrantedAuthority)
+
+    fun isAuthenticated(): Boolean {
+        if (getSecurityContext().authentication == null) {
+            throw UnauthorizedAccessException("User is not authenticated")
+        }
+        return true
+    }
+
+    fun register(registerRequest: RegisterRequest): AuthResponse {
+        if (this.korisnikRepository.findByEmail(registerRequest.email) != null) {
+            throw RuntimeException("Invalid credentials")
+        }
+        if (registerRequest.password != registerRequest.confirmPassword) {
+            throw RuntimeException("Passwords do not match")
+        }
+
+        val roles = this.roleRepository.findAllByNameLikeIgnoreCase("role_passenger")
+
+        val user =
+            this.korisnikRepository.save(
+                Korisnik(
+                    email = registerRequest.email,
+                    lozinka = registerRequest.password,
+                    ime = registerRequest.name,
+                    id = 0L,
+                    adresa = registerRequest.address,
+                    admin = false,
+                    telefon = registerRequest.phoneNumber,
+                    roles = null,
+                ),
+            )
+
+        val newRoles =
+            roles.map {
+                this.korisnikRoleRepository.save(
+                    KorisnikRole(
+                        id = 0,
+                        role = it,
+                        korisnik = user,
+                    ),
+                )
+            }
+
+        user.roles = newRoles
+
+        val korisnik = this.korisnikRepository.save(user)
+        val patnik =
+            this.patnikRepository.save(
+                Patnik(
+                    id = 0L,
+                    korisnik = korisnik,
+                ),
+            )
+
+        return this.authenticate(AuthRequest(user.email, user.lozinka))
+    }
+
+    fun authenticate(authRequest: AuthRequest): AuthResponse {
+        authenticationManager.authenticate(
+            UsernamePasswordAuthenticationToken(
+                authRequest.email,
+                authRequest.password,
+            ),
+        )
+
+        val user = userDetailsService.loadUserByUsername(authRequest.email)
+
+        val token = jwtService.generateToken(userDetails = user)
+
+        return AuthResponse(token)
+    }
+
+    fun isDriverFree(): Boolean {
+        if (!this.hasAuthority(RoleEnum.ROLE_DRIVER)) throw UnauthorizedAccessException("User is not authorized")
+        val korisnik = this.userDetailsService.loadUserByUsername(this.getSecurityContext().authentication.name) as Korisnik
+        val vraboten = this.vrabotenRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Vraboten not found")
+        val vozac = this.vozacRepository.findByVraboten(vraboten) ?: throw NotFoundException("Vozac not found")
+
+        return !this.instancaNaLinijaRepository.existsByVozacAndEndDateIsNull(vozac.id)
+    }
+
+    fun getConductor(): Kondukter {
+        if (!this.isAuthenticated() || !this.hasAuthority(RoleEnum.ROLE_CONDUCTOR)) {
+            throw UnauthorizedAccessException("Unauthorized access")
+        }
+
+        val korisnik = this.getAuthenticatedUser()
+        val vraboten = vrabotenRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Korisnik")
+        val kondukter = kondukterRepository.findByVraboten(vraboten) ?: throw NotFoundException("Kondukter")
+
+        return kondukter
+    }
+
+    fun getDriver(): Vozac {
+        if (!this.isAuthenticated() || !this.hasAuthority(RoleEnum.ROLE_DRIVER)) {
+            throw UnauthorizedAccessException("Unauthorized access")
+        }
+
+        val korisnik = this.getAuthenticatedUser()
+        val vraboten = vrabotenRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Korisnik")
+        val vozac = vozacRepository.findByVraboten(vraboten) ?: throw NotFoundException("Vozac")
+
+        return vozac
+    }
+
+    fun getPassenger(): Patnik {
+        if (!this.isAuthenticated() || !this.hasAuthority(RoleEnum.ROLE_PASSENGER)) {
+            throw UnauthorizedAccessException("Unauthorized access")
+        }
+
+        val korisnik = this.getAuthenticatedUser()
+        val patnik = patnikRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Patnik")
+
+        return patnik
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/BiletService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/BiletService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/BiletService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,65 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.api.requests.TicketBuyRequest
+import mk.ukim.finki.busngobackend.api.responses.TicketResponse
+import mk.ukim.finki.busngobackend.domain.entities.Bilet
+import mk.ukim.finki.busngobackend.domain.enums.BiletEnum
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.BiletRepository
+import mk.ukim.finki.busngobackend.repository.PatnikRepository
+import mk.ukim.finki.busngobackend.repository.TipbiletRepository
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+import java.time.LocalDateTime
+
+@Service
+class BiletService(
+    private val mapper: ClassToDtoMapper,
+    private val biletRepository: BiletRepository,
+    private val korisnikService: KorisnikService,
+    private val patnikRepository: PatnikRepository,
+    private val tipbiletRepository: TipbiletRepository,
+) {
+    fun getTicketsByUser(): List<TicketResponse> {
+        val user = korisnikService.getUser()
+        val patnik =
+            patnikRepository.findByKorisnik(user) ?: throw NotFoundException("Patnik not found")
+
+        return biletRepository.findAllByPatnik(patnik).map { mapper.toTicketResponse(it) }
+    }
+
+    fun buyTicket(request: TicketBuyRequest): TicketResponse {
+        val user = korisnikService.getUser()
+        val patnik =
+            patnikRepository.findByKorisnik(user) ?: throw NotFoundException("Patnik not found")
+        val type = tipbiletRepository.findByIdOrNull(request.type) ?: throw NotFoundException("Type not found")
+
+        val ticket =
+            biletRepository.save(
+                Bilet(
+                    id = 0L,
+                    status = BiletEnum.INACTIVE,
+                    tip = type,
+                    datumKupuvanje = Timestamp.valueOf(LocalDateTime.now()),
+                    patnik = patnik,
+                    datumAktivacija = null,
+                ),
+            )
+
+        return mapper.toTicketResponse(ticket)
+    }
+
+    fun activateTicket(id: Long): TicketResponse {
+        val user = korisnikService.getUser()
+        val patnik =
+            patnikRepository.findByKorisnik(user) ?: throw NotFoundException("Patnik not found")
+
+        val ticket = biletRepository.findByIdAndPatnik(id, patnik) ?: throw NotFoundException("Ticket not found")
+
+        ticket.status = BiletEnum.ACTIVE
+        ticket.datumAktivacija = Timestamp.valueOf(LocalDateTime.now())
+        return mapper.toTicketResponse(biletRepository.save(ticket))
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/BusService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/BusService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/BusService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,14 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.domain.entities.Avtobus
+import mk.ukim.finki.busngobackend.repository.AvtobusRepository
+import org.springframework.stereotype.Service
+
+@Service
+class BusService(
+    private val avtobusRepository: AvtobusRepository,
+) {
+    fun findAll() = avtobusRepository.findAll()
+
+    fun findAllFree(): List<Avtobus> = this.avtobusRepository.findAllFreeBuses()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/CommuteService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/CommuteService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/CommuteService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,66 @@
+package mk.ukim.finki.busngobackend.service
+
+import jakarta.transaction.Transactional
+import mk.ukim.finki.busngobackend.api.requests.StartCommuteRequest
+import mk.ukim.finki.busngobackend.api.responses.CommuteResponse
+import mk.ukim.finki.busngobackend.domain.entities.Vozenje
+import mk.ukim.finki.busngobackend.domain.enums.BiletEnum
+import mk.ukim.finki.busngobackend.domain.enums.RoleEnum
+import mk.ukim.finki.busngobackend.domain.enums.VozenjeStatus
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.*
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import mk.ukim.finki.busngobackend.service.exceptions.UnauthorizedAccessException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+import java.time.LocalDateTime
+
+@Service
+class CommuteService(
+    private val linijaRepository: LinijaRepository,
+    private val postojkaRepository: PostojkaRepository,
+    private val postojkaNaLinijaRepository: PostojkaNaLinijaRepository,
+    private val biletRepository: BiletRepository,
+    private val authService: AuthService,
+    private val patnikRepository: PatnikRepository,
+    private val instancaNaLinijaRepository: InstancaNaLinijaRepository,
+    private val vozenjeRepository: VozenjeRepository,
+    private val dtoMapper: ClassToDtoMapper,
+) {
+    @Transactional
+    fun start(request: StartCommuteRequest): CommuteResponse {
+        if (!this.authService.hasAuthority(RoleEnum.ROLE_PASSENGER)) throw UnauthorizedAccessException("Unauthorised role")
+        val korisnik = this.authService.getAuthenticatedUser()
+        val patnik = patnikRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Korisnik")
+
+        var bilet = biletRepository.findByIdAndPatnik(request.ticketId, patnik) ?: throw NotFoundException("Bilet")
+
+        val instancaNaLinija =
+            instancaNaLinijaRepository.findByIdOrNull(request.routeInstanceId) ?: throw NotFoundException("RouteInstanceId")
+        val postojka = postojkaRepository.findByIdOrNull(request.stationId) ?: throw NotFoundException("StationId")
+
+        val postojkaNaLinijaStart =
+            postojkaNaLinijaRepository.findByLinijaAndPostojkaAndPravec(instancaNaLinija.linija, postojka, instancaNaLinija.pravec)
+                ?: throw NotFoundException("Station not found")
+
+        if (bilet.status == BiletEnum.INACTIVE) {
+            bilet.status = BiletEnum.ACTIVE
+            bilet.datumAktivacija = Timestamp.valueOf(LocalDateTime.now())
+            bilet = biletRepository.save(bilet)
+        }
+
+        val vozenje =
+            Vozenje(
+                id = 0L,
+                startDate = Timestamp.valueOf(LocalDateTime.now()),
+                endDate = null,
+                status = VozenjeStatus.ACTIVE,
+                patnik = patnik,
+                postojkaNaLinijaStart = postojkaNaLinijaStart,
+                instancaNaLinija = instancaNaLinija,
+                bilet = bilet,
+            )
+        return vozenjeRepository.save(vozenje).let { dtoMapper.toCommuteResponse(it) }
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/ControlService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/ControlService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/ControlService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,61 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.api.responses.ControlResponse
+import mk.ukim.finki.busngobackend.api.responses.FineResponse
+import mk.ukim.finki.busngobackend.domain.entities.Kontrola
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.*
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+import java.time.LocalDateTime
+
+@Service
+class ControlService(
+    private val kontrolaRepository: KontrolaRepository,
+    private val dtoMapper: ClassToDtoMapper,
+    private val authService: AuthService,
+    private val instancaNaLinijaRepository: InstancaNaLinijaRepository,
+    private val kaznaRepository: KaznaRepository,
+    private val kaznaZaRegistriranRepository: KaznaZaRegistriranRepository,
+    private val kaznaZaNeregistriranRepository: KaznaZaNeregistriranRepository,
+) {
+    fun getAllByConductor(): List<ControlResponse> {
+        val kondukter = authService.getConductor()
+
+        return kontrolaRepository
+            .findAllByKondukterOrderByDateCreatedDesc(
+                kondukter,
+            ).map { kontrola -> dtoMapper.toControlResponse(kontrola) }
+    }
+
+    fun start(routeInstanceId: Long): ControlResponse {
+        val instancaNaLinija =
+            instancaNaLinijaRepository.findByIdOrNull(routeInstanceId) ?: throw NotFoundException("Route instance")
+        val kontrola =
+            kontrolaRepository.save(
+                Kontrola(
+                    id = 0L,
+                    kondukter = authService.getConductor(),
+                    dateCreated = Timestamp.valueOf(LocalDateTime.now()),
+                    instancaNaLinija = instancaNaLinija,
+                ),
+            )
+        return kontrola.let { dtoMapper.toControlResponse(it) }
+    }
+
+    fun getFines(controlId: Long): List<FineResponse> {
+        val kondukter = authService.getConductor()
+        val kontrola = kontrolaRepository.findByIdOrNull(controlId) ?: throw NotFoundException("Control not found")
+
+        val kazni = kaznaRepository.findAllByKontrola(kontrola)
+
+        val kzrs = kaznaZaRegistriranRepository.findAllByKaznaIn(kazni)
+        val kzns = kaznaZaNeregistriranRepository.findAllByKaznaIn(kazni)
+
+        return kzrs
+            .map { dtoMapper.toFineResponse(kazna = it.kazna, kzr = it, kzn = null) }
+            .plus(kzns.map { dtoMapper.toFineResponse(kazna = it.kazna, kzr = null, kzn = it) })
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/DirectionService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/DirectionService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/DirectionService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,21 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.domain.entities.LinijaPravec
+import mk.ukim.finki.busngobackend.repository.LinijaPravecRepository
+import mk.ukim.finki.busngobackend.repository.LinijaRepository
+import mk.ukim.finki.busngobackend.repository.PravecRepository
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+
+@Service
+class DirectionService(
+    private val pravecRepository: PravecRepository,
+    private val linijaPravecRepository: LinijaPravecRepository,
+    private val linijaRepository: LinijaRepository,
+) {
+    fun findDirectionsByLineId(lineId: Int): List<LinijaPravec> {
+        val linija = linijaRepository.findByIdOrNull(lineId) ?: throw NotFoundException("Line not found")
+        return linijaPravecRepository.findAllByLinija(linija)
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/FineService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/FineService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/FineService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,81 @@
+package mk.ukim.finki.busngobackend.service
+
+import jakarta.transaction.Transactional
+import mk.ukim.finki.busngobackend.api.requests.FineRequest
+import mk.ukim.finki.busngobackend.api.responses.FineResponse
+import mk.ukim.finki.busngobackend.domain.entities.Kazna
+import mk.ukim.finki.busngobackend.domain.entities.KaznaZaNeregistriran
+import mk.ukim.finki.busngobackend.domain.entities.KaznaZaRegistriran
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.*
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+import java.time.LocalDateTime
+
+@Service
+class FineService(
+    private val kaznaRepository: KaznaRepository,
+    private val authService: AuthService,
+    private val kontrolaRepository: KontrolaRepository,
+    private val dtoMapper: ClassToDtoMapper,
+    private val kaznaZaRegistriranRepository: KaznaZaRegistriranRepository,
+    private val kaznaZaNeregistriranRepository: KaznaZaNeregistriranRepository,
+    private val korisnikRepository: KorisnikRepository,
+    private val patnikRepository: PatnikRepository,
+) {
+    @Transactional
+    fun createFine(request: FineRequest): FineResponse {
+        val kontrola = kontrolaRepository.findByIdOrNull(request.kontrolaId) ?: throw NotFoundException("Kontrola")
+        val now = Timestamp.valueOf(LocalDateTime.now())
+        val kazna =
+            kaznaRepository.save(
+                Kazna(
+                    dateCreated = now,
+                    id = 0L,
+                    kondukter = authService.getConductor(),
+                    datePayed =
+                        if (request.plateno) {
+                            now
+                        } else {
+                            null
+                        },
+                    iznos = request.iznos,
+                    dokument = request.dokument,
+                    kontrola = kontrola,
+                    plateno = request.plateno,
+                ),
+            )
+
+        if (request.patnikId != null) {
+            val korisnik = korisnikRepository.findByIdOrNull(request.patnikId!!) ?: throw NotFoundException("Korisnik")
+            val patnik = patnikRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Patnik")
+            val kzr =
+                kaznaZaRegistriranRepository.save(
+                    KaznaZaRegistriran(
+                        patnik = patnik,
+                        id = 0L,
+                        kazna = kazna,
+                    ),
+                )
+            return kzr.let { dtoMapper.toFineResponse(kazna = kazna, kzr = kzr, kzn = null) }
+        }
+
+        if (request.adresa != null && request.ime != null && request.telefon != null) {
+            val kzn =
+                kaznaZaNeregistriranRepository.save(
+                    KaznaZaNeregistriran(
+                        id = 0L,
+                        kazna = kazna,
+                        ime = request.ime!!,
+                        telefon = request.telefon!!,
+                        adresa = request.adresa!!,
+                    ),
+                )
+
+            return kzn.let { dtoMapper.toFineResponse(kazna = kazna, kzn = kzn, kzr = null) }
+        }
+        return dtoMapper.toFineResponse(kazna = kazna, kzr = null, kzn = null)
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/KorisnikService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/KorisnikService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/KorisnikService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,36 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.api.responses.UserResponse
+import mk.ukim.finki.busngobackend.domain.entities.Korisnik
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.KorisnikRepository
+import mk.ukim.finki.busngobackend.repository.PatnikRepository
+import mk.ukim.finki.busngobackend.service.exceptions.UnauthorizedAccessException
+import org.springframework.stereotype.Service
+
+@Service
+class KorisnikService(
+    private val korisnikRepository: KorisnikRepository,
+    private val authService: AuthService,
+    private val mapper: ClassToDtoMapper,
+    private val patnikRepository: PatnikRepository,
+    private val classToDtoMapper: ClassToDtoMapper,
+) {
+    fun getAuthenticatedUser(): UserResponse {
+        val user =
+            authService.getSecurityContext().authentication?.let { auth ->
+                korisnikRepository.findByEmail(auth.name)
+            }
+
+        return user?.let { mapper.toUserResponse(it) } ?: throw UnauthorizedAccessException("Unauthorized access")
+    }
+
+    fun getUser(): Korisnik =
+        authService.getSecurityContext().authentication?.let { auth ->
+            korisnikRepository.findByEmail(auth.name)
+        } ?: throw UnauthorizedAccessException("Unauthorized access")
+
+    fun getAllPassengers(): List<UserResponse> = patnikRepository.findAll().map { classToDtoMapper.toUserResponse(it.korisnik) }
+
+    fun getAllUsers() = korisnikRepository.findAll().map { classToDtoMapper.toAdminUsersResponse(it) }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/LineService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/LineService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/LineService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,14 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.domain.entities.Linija
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.LinijaRepository
+import org.springframework.stereotype.Service
+
+@Service
+class LineService(
+    private val linijaRepository: LinijaRepository,
+    private val dtoMapper: ClassToDtoMapper,
+) {
+    fun findAllLines(): List<Linija> = this.linijaRepository.findAll()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/MaterializedViewService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/MaterializedViewService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/MaterializedViewService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,34 @@
+package mk.ukim.finki.busngobackend.service
+
+import org.springframework.jdbc.core.JdbcTemplate
+import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
+
+@Service
+class MaterializedViewService(
+    private val jdbcTemplate: JdbcTemplate,
+) {
+    @Transactional
+    fun refreshAverageTimeDiffs() {
+        val sql = "REFRESH MATERIALIZED VIEW CONCURRENTLY project.avg_time_diffs;"
+        jdbcTemplate.execute(sql)
+    }
+
+    @Transactional
+    fun refreshCommutesByHour() {
+        val sql = "refresh materialized view concurrently project.most_busy_part_of_the_day;"
+        jdbcTemplate.execute(sql)
+    }
+
+    @Transactional
+    fun refreshFinesPerLine() {
+        val sql = "refresh materialized view concurrently project.kazna_po_linija;"
+        jdbcTemplate.execute(sql)
+    }
+
+    @Transactional
+    fun refreshTotalIncome() {
+        val sql = "refresh materialized view concurrently project.total_income;"
+        jdbcTemplate.execute(sql)
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/RouteInstanceOnStationService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/RouteInstanceOnStationService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/RouteInstanceOnStationService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,35 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinijaPostojkaNaLinija
+import mk.ukim.finki.busngobackend.repository.InstancaNaLinijaPostojkaNaLinijaRepository
+import mk.ukim.finki.busngobackend.repository.InstancaNaLinijaRepository
+import mk.ukim.finki.busngobackend.repository.PostojkaNaLinijaRepository
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+
+@Service
+class RouteInstanceOnStationService(
+    private val instancaNaLinijaPostojkaNaLinijaRepository: InstancaNaLinijaPostojkaNaLinijaRepository,
+    private val instancaNaLinijaRepository: InstancaNaLinijaRepository,
+    private val postojkaNaLinijaRepository: PostojkaNaLinijaRepository,
+) {
+    fun create(
+        routeInstanceId: Long,
+        lineStationId: Long,
+        timestamp: Timestamp,
+    ): InstancaNaLinijaPostojkaNaLinija {
+        val routeInstance =
+            instancaNaLinijaRepository.findByIdOrNull(routeInstanceId) ?: throw NotFoundException("Route instance not found")
+        val lineStation = postojkaNaLinijaRepository.findByIdOrNull(lineStationId) ?: throw NotFoundException("Line station not found")
+        return instancaNaLinijaPostojkaNaLinijaRepository.save(
+            InstancaNaLinijaPostojkaNaLinija(
+                instancaNaLinija = routeInstance,
+                postojkaNaLinija = lineStation,
+                timestamp = timestamp,
+                id = 0L,
+            ),
+        )
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/RouteInstanceService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/RouteInstanceService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/RouteInstanceService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,96 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.api.requests.StartRouteInstanceRequest
+import mk.ukim.finki.busngobackend.api.responses.RouteInstanceResponse
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import mk.ukim.finki.busngobackend.domain.enums.RoleEnum
+import mk.ukim.finki.busngobackend.events.StartRouteEvent
+import mk.ukim.finki.busngobackend.mapper.ClassToDtoMapper
+import mk.ukim.finki.busngobackend.repository.*
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import mk.ukim.finki.busngobackend.service.exceptions.UnauthorizedAccessException
+import org.springframework.context.ApplicationEventPublisher
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+import java.time.LocalDateTime
+
+@Service
+class RouteInstanceService(
+    private val instancaNaLinijaRepository: InstancaNaLinijaRepository,
+    private val linijaRepository: LinijaRepository,
+    private val pravecRepository: PravecRepository,
+    private val linijaPravecRepository: LinijaPravecRepository,
+    private val avtobusRepository: AvtobusRepository,
+    private val authService: AuthService,
+    private val vrabotenRepository: VrabotenRepository,
+    private val vozacRepository: VozacRepository,
+    private val dtoMapper: ClassToDtoMapper,
+    private val publisher: ApplicationEventPublisher,
+    private val postojkaRepository: PostojkaRepository,
+) {
+    fun start(request: StartRouteInstanceRequest): RouteInstanceResponse {
+        if (!authService.isAuthenticated() || !authService.hasAuthority(RoleEnum.ROLE_DRIVER)) {
+            throw UnauthorizedAccessException("Unauthorized access")
+        }
+
+        val korisnik = authService.getAuthenticatedUser()
+        val vraboten = vrabotenRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Korisnik")
+        val vozac = vozacRepository.findByVraboten(vraboten) ?: throw NotFoundException("Vraboten")
+
+        val linija = linijaRepository.findByIdOrNull(request.lineId) ?: throw NotFoundException("Line not found")
+        val pravec =
+            pravecRepository.findByIdOrNull(request.directionId) ?: throw NotFoundException("Direction not found")
+
+        if (!linijaPravecRepository.existsByLinijaAndPravec(linija, pravec)) {
+            throw NotFoundException("Line does not has the specified direction")
+        }
+
+        val avtobus = avtobusRepository.findByIdOrNull(request.busId) ?: throw NotFoundException("Bus Not Found")
+
+        val instanca =
+            InstancaNaLinija(
+                id = 0L,
+                startDate = Timestamp.valueOf(LocalDateTime.now()),
+                linija = linija,
+                pravec = pravec,
+                avtobus = avtobus,
+                vozac = vozac,
+                endDate = null,
+            )
+
+        return instancaNaLinijaRepository
+            .save(instanca)
+            .let {
+                publisher.publishEvent(StartRouteEvent(it))
+                dtoMapper.toRouteInstanceResponse(it)
+            }
+    }
+
+    fun findById(id: Long): InstancaNaLinija = instancaNaLinijaRepository.findByIdOrNull(id) ?: throw NotFoundException("id not found")
+
+    fun stop(id: Long): RouteInstanceResponse {
+        val instance = this.findById(id)
+        if (instance.endDate != null) throw UnauthorizedAccessException("Unauthorized access")
+        instance.endDate = Timestamp.valueOf(LocalDateTime.now())
+        return instancaNaLinijaRepository.save(instance).let { dtoMapper.toRouteInstanceResponse(it) }
+    }
+
+    fun getById(id: Long): RouteInstanceResponse {
+        val ri = this.findById(id)
+        val korisnik = this.authService.getAuthenticatedUser()
+        if (korisnik.id != ri.vozac.vraboten.korisnik.id) throw UnauthorizedAccessException("Unauthorized access")
+        return dtoMapper.toRouteInstanceResponse(this.findById(id))
+    }
+
+    fun getForStation(stationId: Long): List<RouteInstanceResponse> {
+        val station = postojkaRepository.findByIdOrNull(stationId) ?: throw NotFoundException("Station not found")
+        // find all route instances heading to the given station
+        val routeInstanceIds = instancaNaLinijaRepository.findIncomingRouteInstancesForStation(station.id)
+        val routeInstances = instancaNaLinijaRepository.findAllById(routeInstanceIds)
+        return routeInstances.map { dtoMapper.toRouteInstanceResponse(it) }
+    }
+
+    fun getAll(): List<RouteInstanceResponse> =
+        instancaNaLinijaRepository.findAllByEndDateIsNull().map { dtoMapper.toRouteInstanceResponse(it) }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/StationService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/StationService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/StationService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,40 @@
+package mk.ukim.finki.busngobackend.service
+
+import mk.ukim.finki.busngobackend.domain.entities.Postojka
+import mk.ukim.finki.busngobackend.domain.entities.PostojkaNaLinija
+import mk.ukim.finki.busngobackend.repository.LinijaRepository
+import mk.ukim.finki.busngobackend.repository.PostojkaNaLinijaRepository
+import mk.ukim.finki.busngobackend.repository.PostojkaRepository
+import mk.ukim.finki.busngobackend.repository.PravecRepository
+import mk.ukim.finki.busngobackend.service.exceptions.NotFoundException
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+
+@Service
+class StationService(
+    private val postojkaRepository: PostojkaRepository,
+    private val postojkaNaLinijaRepository: PostojkaNaLinijaRepository,
+    private val linijaRepository: LinijaRepository,
+    private val pravecRepository: PravecRepository,
+) {
+    fun findStationsByLineId(lineId: Int): List<PostojkaNaLinija> {
+        val linija = linijaRepository.findByIdOrNull(lineId) ?: throw NotFoundException("Linija not found")
+        return this.postojkaNaLinijaRepository.findByLinija(linija)
+    }
+
+    fun findStationsByLineIdAndDirectionId(
+        lineId: Int,
+        directionId: Long?,
+    ): List<PostojkaNaLinija> {
+        if (directionId == null) {
+            return this.findStationsByLineId(lineId)
+        }
+
+        val linija = linijaRepository.findByIdOrNull(lineId) ?: throw NotFoundException("Linija not found")
+        val pravec = pravecRepository.findByIdOrNull(directionId) ?: throw NotFoundException("Pravec not found")
+
+        return postojkaNaLinijaRepository.findByLinijaAndPravec(linija, pravec)
+    }
+
+    fun getAll(): List<Postojka> = this.postojkaRepository.findAll()
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/WebSocketService.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/WebSocketService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/WebSocketService.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,16 @@
+package mk.ukim.finki.busngobackend.service
+
+import org.springframework.messaging.simp.SimpMessagingTemplate
+import org.springframework.stereotype.Service
+
+@Service
+class WebSocketService(
+    private val messagingTemplate: SimpMessagingTemplate,
+) {
+    fun sendMessage(
+        topicSuffix: String,
+        message: String,
+    ) {
+        messagingTemplate.convertAndSend("/topic/$topicSuffix", message)
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/exceptions/NotFoundException.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/exceptions/NotFoundException.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/exceptions/NotFoundException.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,5 @@
+package mk.ukim.finki.busngobackend.service.exceptions
+
+class NotFoundException(
+    message: String,
+) : RuntimeException(message)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/exceptions/UnauthorizedAccessException.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/exceptions/UnauthorizedAccessException.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/service/exceptions/UnauthorizedAccessException.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,5 @@
+package mk.ukim.finki.busngobackend.service.exceptions
+
+class UnauthorizedAccessException(
+    s: String,
+) : RuntimeException(s)
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/simulator/DummyDataPopulator.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/simulator/DummyDataPopulator.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/simulator/DummyDataPopulator.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,208 @@
+package mk.ukim.finki.busngobackend.simulator
+
+import mk.ukim.finki.busngobackend.domain.entities.*
+import mk.ukim.finki.busngobackend.domain.enums.BiletEnum
+import mk.ukim.finki.busngobackend.domain.enums.VozenjeStatus
+import mk.ukim.finki.busngobackend.repository.*
+import org.springframework.stereotype.Service
+import java.sql.Timestamp
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.util.concurrent.ThreadLocalRandom
+
+@Service
+class DummyDataPopulator(
+    private val linijaRepository: LinijaRepository,
+    private val vozacRepository: VozacRepository,
+    private val avtobusRepository: AvtobusRepository,
+    private val linijaPravecRepository: LinijaPravecRepository,
+    private val postojkaNaLinijaRepository: PostojkaNaLinijaRepository,
+    private val instancaNaLinijaRepository: InstancaNaLinijaRepository,
+    private val instancaNaLinijaPostojkaNaLinijaRepository: InstancaNaLinijaPostojkaNaLinijaRepository,
+    private val vozenjeRepository: VozenjeRepository,
+    private val patnikRepository: PatnikRepository,
+    private val biletRepository: BiletRepository,
+    private val tipbiletRepository: TipbiletRepository,
+    private val kaznaRepository: KaznaRepository,
+    private val kontrolaRepository: KontrolaRepository,
+    private val kondukterRepository: KondukterRepository,
+    private val kaznaZaNeregistriranRepository: KaznaZaNeregistriranRepository,
+) {
+    fun populateFines() {
+        val routeInstances = instancaNaLinijaRepository.findAll()
+        val kondukters = kondukterRepository.findAll()
+
+        routeInstances.forEach { inl ->
+            run {
+                val kondukter = kondukters.random()
+                val kontrola =
+                    kontrolaRepository.save(
+                        Kontrola(
+                            id = 0L,
+                            instancaNaLinija = inl,
+                            dateCreated = getRandomTimestamp(inl.startDate.toLocalDateTime(), inl.endDate!!.toLocalDateTime()),
+                            kondukter = kondukter,
+                        ),
+                    )
+                for (i in 0..5) {
+                    val kazna =
+                        kaznaRepository.save(
+                            Kazna(
+                                id = 0L,
+                                iznos = 1000.0,
+                                dokument = "DOC " + LocalDateTime.now().toString(),
+                                kontrola = kontrola,
+                                dateCreated = getRandomTimestamp(kontrola.dateCreated.toLocalDateTime(), inl.endDate!!.toLocalDateTime()),
+                                datePayed = getRandomTimestamp(kontrola.dateCreated.toLocalDateTime(), inl.endDate!!.toLocalDateTime()),
+                                kondukter = kondukter,
+                                plateno = true,
+                            ),
+                        )
+
+                    kaznaZaNeregistriranRepository.save(
+                        KaznaZaNeregistriran(
+                            id = 0L,
+                            kazna = kazna,
+                            ime = "Test Ime" + LocalDateTime.now().toString(),
+                            adresa = "Test Adres" + LocalDateTime.now().toString(),
+                            telefon = "+38975123456",
+                        ),
+                    )
+                }
+            }
+        }
+    }
+
+    fun populateCommutes() {
+        val routeInstances = instancaNaLinijaRepository.findAll()
+        routeInstances.forEach { instancaNaLinija ->
+            run {
+                val patnik = patnikRepository.findAll().random()
+                val startDate =
+                    getRandomTimestamp(
+                        instancaNaLinija.startDate.toLocalDateTime(),
+                        instancaNaLinija.endDate!!.toLocalDateTime(),
+                    )
+                val bilet =
+                    biletRepository.findAll().randomOrNull() ?: biletRepository.save(
+                        Bilet(
+                            id = 0L,
+                            datumKupuvanje = startDate,
+                            datumAktivacija = startDate,
+                            status = BiletEnum.ACTIVE,
+                            patnik = patnik,
+                            tip = tipbiletRepository.findAll().random(),
+                        ),
+                    )
+                val postojkaNaLinijaStart =
+                    instancaNaLinijaPostojkaNaLinijaRepository.findByInstancaNaLinijaAndTimestampNearestTo(
+                        instancaNaLinija.id,
+                        startDate,
+                    )
+                vozenjeRepository.save(
+                    Vozenje(
+                        id = 0L,
+                        startDate = startDate,
+                        instancaNaLinija = instancaNaLinija,
+                        postojkaNaLinijaStart =
+                            postojkaNaLinijaStart?.postojkaNaLinija
+                                ?: postojkaNaLinijaRepository.findByLinija(instancaNaLinija.linija).random(),
+                        patnik = patnik,
+                        endDate = instancaNaLinija.endDate,
+                        bilet = bilet,
+                        status = VozenjeStatus.FINISHED,
+                    ),
+                )
+            }
+        }
+    }
+
+    fun populateRouteInstances() {
+        val lines = linijaRepository.findAll()
+        val drivers = vozacRepository.findAll()
+        val buses = avtobusRepository.findAll()
+
+        lines.forEach { randomLine ->
+            run {
+                val directionsForRandomLine = linijaPravecRepository.findAllByLinija(randomLine).map { it.pravec }
+                for (i in 0..10) {
+                    val randomDirection = directionsForRandomLine.random()
+                    val startDate =
+                        getRandomTimestamp(
+                            start = LocalDateTime.of(2020, 1, 1, 0, 0),
+                            end = LocalDateTime.now(),
+                        )
+
+                    val instance =
+                        instancaNaLinijaRepository.save(
+                            InstancaNaLinija(
+                                startDate = startDate,
+                                endDate = null,
+                                id = 0L,
+                                vozac = drivers.random(),
+                                linija = randomLine,
+                                avtobus = buses.random(),
+                                pravec = randomDirection,
+                            ),
+                        )
+
+                    val stationsForRandomLine =
+                        postojkaNaLinijaRepository
+                            .findByLinijaAndPravec(
+                                randomLine,
+                                randomDirection,
+                            ).sortedBy { it.redenBroj }
+                    var lastTime = Timestamp.valueOf(LocalDateTime.now())
+                    stationsForRandomLine.forEach { station ->
+                        run {
+                            if (station.redenBroj.toInt() == 1) {
+                                val start = instance.startDate.toLocalDateTime().plusMinutes(1)
+                                lastTime = getRandomTimestamp(start = start, end = start.plusMinutes(12))
+                            } else {
+                                val start = lastTime.toLocalDateTime().plusMinutes(1)
+                                lastTime = getRandomTimestamp(start = start, end = start.plusMinutes(12))
+                            }
+                            instancaNaLinijaPostojkaNaLinijaRepository.save(
+                                InstancaNaLinijaPostojkaNaLinija(
+                                    id = 0L,
+                                    instancaNaLinija = instance,
+                                    postojkaNaLinija = station,
+                                    timestamp = lastTime,
+                                ),
+                            )
+                        }
+                    }
+                    instance.endDate = lastTime
+                    instancaNaLinijaRepository.save(instance)
+                }
+            }
+        }
+    }
+
+    private fun getRandomTimestamp(
+        start: LocalDateTime,
+        end: LocalDateTime,
+    ): Timestamp {
+        // Define the start time (January 1, 2020, 00:00:00)
+//        val start = LocalDateTime.of(2020, 1, 1, 0, 0)
+        // Get the current time
+//        val end = LocalDateTime.now()
+
+        // Convert LocalDateTime to milliseconds since epoch
+        val startMillis = start.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
+        val endMillis = end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
+
+        // Generate a random time between startMillis and endMillis
+        val randomMillis = ThreadLocalRandom.current().nextLong(startMillis, endMillis)
+
+        // Convert milliseconds back to LocalDateTime
+        val randomLocalDateTime =
+            LocalDateTime.ofInstant(
+                java.time.Instant.ofEpochMilli(randomMillis),
+                ZoneId.systemDefault(),
+            )
+
+        // Convert LocalDateTime to Timestamp
+        return Timestamp.valueOf(randomLocalDateTime)
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/simulator/RouteInstanceSimulator.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/simulator/RouteInstanceSimulator.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/simulator/RouteInstanceSimulator.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,43 @@
+package mk.ukim.finki.busngobackend.simulator
+
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import mk.ukim.finki.busngobackend.domain.entities.InstancaNaLinija
+import mk.ukim.finki.busngobackend.domain.entities.PostojkaNaLinija
+import mk.ukim.finki.busngobackend.domain.helpers.RouteInstanceOnStation
+import mk.ukim.finki.busngobackend.events.RouteInstanceOnStationEvent
+import mk.ukim.finki.busngobackend.events.StopRouteInstanceEvent
+import org.springframework.context.ApplicationEventPublisher
+import org.springframework.scheduling.annotation.Async
+import org.springframework.stereotype.Component
+import java.sql.Timestamp
+import java.time.LocalDateTime
+
+@Component
+class RouteInstanceSimulator(
+    private val eventPublisher: ApplicationEventPublisher,
+) {
+    @Async
+    fun simulate(
+        instance: InstancaNaLinija,
+        stations: List<PostojkaNaLinija>,
+    ) {
+        runBlocking {
+            stations.forEach { station ->
+                delay(1000 * 20)
+                eventPublisher.publishEvent(
+                    RouteInstanceOnStationEvent(
+                        RouteInstanceOnStation(
+                            instance,
+                            station,
+                            Timestamp.valueOf(
+                                LocalDateTime.now(),
+                            ),
+                        ),
+                    ),
+                )
+            }
+        }
+        eventPublisher.publishEvent(StopRouteInstanceEvent(instance))
+    }
+}
Index: bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/tasks/RefreshMaterializedViews.kt
===================================================================
--- bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/tasks/RefreshMaterializedViews.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
+++ bus-n-go-pavel-216049/bus-n-go-backend/src/main/kotlin/mk/ukim/finki/busngobackend/tasks/RefreshMaterializedViews.kt	(revision baf4cc4b66f1d62e9dc9c2e71bcc078c9c3956a3)
@@ -0,0 +1,18 @@
+package mk.ukim.finki.busngobackend.tasks
+
+import mk.ukim.finki.busngobackend.service.MaterializedViewService
+import org.springframework.scheduling.annotation.Scheduled
+import org.springframework.stereotype.Service
+
+@Service
+class RefreshMaterializedViews(
+    private val materializedViewService: MaterializedViewService,
+) {
+    @Scheduled(fixedRateString = "\${materialized.view.refresh.rate}")
+    fun refreshMaterializedViewTask() {
+        materializedViewService.refreshAverageTimeDiffs()
+        materializedViewService.refreshCommutesByHour()
+        materializedViewService.refreshFinesPerLine()
+        materializedViewService.refreshTotalIncome()
+    }
+}
