| | 221 | |
| | 222 | == Интегритет |
| | 223 | |
| | 224 | === Тригери |
| | 225 | |
| | 226 | {{{#!sql |
| | 227 | |
| | 228 | create or replace function check_expiry_date() returns trigger |
| | 229 | as |
| | 230 | $$ |
| | 231 | begin |
| | 232 | if exists( |
| | 233 | select 1 |
| | 234 | from vozenje v |
| | 235 | where v.patnik_id = new.patnik_id and v.end_date is null |
| | 236 | ) then |
| | 237 | update vozenje set end_date = now(), status = 'FINISHED' where id in (select v.id |
| | 238 | from vozenje v |
| | 239 | where v.patnik_id = new.patnik_id and v.end_date is null); |
| | 240 | end if; |
| | 241 | |
| | 242 | if exists( |
| | 243 | select 1 |
| | 244 | from bilet |
| | 245 | where id = new.bilet_id and datum_aktivacija is null |
| | 246 | ) then |
| | 247 | update bilet set datum_aktivacija = now(), status = 'ACTIVE' where id = new.bilet_id; |
| | 248 | end if; |
| | 249 | |
| | 250 | if exists( |
| | 251 | select 1 |
| | 252 | from bilet b |
| | 253 | join tipbilet tb on b.tip_id = tb.id |
| | 254 | where b.id = new.bilet_id and ((b.datum_aktivacija + (tb.trajnost || ' milliseconds')::interval) < now()) |
| | 255 | ) then |
| | 256 | update bilet set status = 'EXPIRED' where id = new.bilet_id; |
| | 257 | end if; |
| | 258 | |
| | 259 | if exists( |
| | 260 | select 1 |
| | 261 | from bilet b |
| | 262 | join tipbilet tb on b.tip_id = tb.id |
| | 263 | where b.id = new.bilet_id and ((b.datum_aktivacija + (tb.trajnost || ' milliseconds')::interval) < now()) |
| | 264 | ) then |
| | 265 | RAISE exception 'Ticket is expired'; |
| | 266 | end if; |
| | 267 | return new; |
| | 268 | end; |
| | 269 | $$ language plpgsql; |
| | 270 | |
| | 271 | create or replace trigger check_validity_of_ticket |
| | 272 | before insert on vozenje |
| | 273 | for each row |
| | 274 | execute function check_expiry_date(); |
| | 275 | |
| | 276 | |
| | 277 | }}} |
| | 278 | |
| | 279 | === Трансакции |
| | 280 | |
| | 281 | {{{#!java |
| | 282 | |
| | 283 | @Transactional |
| | 284 | fun refreshAverageTimeDiffs() { |
| | 285 | val sql = "REFRESH MATERIALIZED VIEW CONCURRENTLY avg_time_diffs;" |
| | 286 | jdbcTemplate.execute(sql) |
| | 287 | } |
| | 288 | |
| | 289 | @Transactional |
| | 290 | fun refreshCommutesByHour() { |
| | 291 | val sql = "refresh materialized view concurrently most_busy_part_of_the_day;" |
| | 292 | jdbcTemplate.execute(sql) |
| | 293 | } |
| | 294 | |
| | 295 | @Transactional |
| | 296 | fun refreshFinesPerLine() { |
| | 297 | val sql = "refresh materialized view concurrently kazna_po_linija;" |
| | 298 | jdbcTemplate.execute(sql) |
| | 299 | } |
| | 300 | |
| | 301 | @Transactional |
| | 302 | fun refreshTotalIncome() { |
| | 303 | val sql = "refresh materialized view concurrently total_income;" |
| | 304 | jdbcTemplate.execute(sql) |
| | 305 | } |
| | 306 | |
| | 307 | }}} |
| | 308 | |
| | 309 | {{{#!java |
| | 310 | @Transactional |
| | 311 | fun createFine(request: FineRequest): FineResponse { |
| | 312 | val kontrola = kontrolaRepository.findByIdOrNull(request.kontrolaId) ?: throw NotFoundException("Kontrola") |
| | 313 | val now = Timestamp.valueOf(LocalDateTime.now()) |
| | 314 | val kazna = |
| | 315 | kaznaRepository.save( |
| | 316 | Kazna( |
| | 317 | dateCreated = now, |
| | 318 | id = 0L, |
| | 319 | kondukter = authService.getConductor(), |
| | 320 | datePayed = |
| | 321 | if (request.plateno) { |
| | 322 | now |
| | 323 | } else { |
| | 324 | null |
| | 325 | }, |
| | 326 | iznos = request.iznos, |
| | 327 | dokument = request.dokument, |
| | 328 | kontrola = kontrola, |
| | 329 | plateno = request.plateno, |
| | 330 | ), |
| | 331 | ) |
| | 332 | |
| | 333 | if (request.patnikId != null) { |
| | 334 | val korisnik = korisnikRepository.findByIdOrNull(request.patnikId!!) ?: throw NotFoundException("Korisnik") |
| | 335 | val patnik = patnikRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Patnik") |
| | 336 | val kzr = |
| | 337 | kaznaZaRegistriranRepository.save( |
| | 338 | KaznaZaRegistriran( |
| | 339 | patnik = patnik, |
| | 340 | id = 0L, |
| | 341 | kazna = kazna, |
| | 342 | ), |
| | 343 | ) |
| | 344 | return kzr.let { dtoMapper.toFineResponse(kazna = kazna, kzr = kzr, kzn = null) } |
| | 345 | } |
| | 346 | |
| | 347 | if (request.adresa != null && request.ime != null && request.telefon != null) { |
| | 348 | val kzn = |
| | 349 | kaznaZaNeregistriranRepository.save( |
| | 350 | KaznaZaNeregistriran( |
| | 351 | id = 0L, |
| | 352 | kazna = kazna, |
| | 353 | ime = request.ime!!, |
| | 354 | telefon = request.telefon!!, |
| | 355 | adresa = request.adresa!!, |
| | 356 | ), |
| | 357 | ) |
| | 358 | |
| | 359 | return kzn.let { dtoMapper.toFineResponse(kazna = kazna, kzn = kzn, kzr = null) } |
| | 360 | } |
| | 361 | return dtoMapper.toFineResponse(kazna = kazna, kzr = null, kzn = null) |
| | 362 | } |
| | 363 | }}} |
| | 364 | |
| | 365 | |
| | 366 | {{{#!java |
| | 367 | |
| | 368 | @Transactional |
| | 369 | fun start(request: StartCommuteRequest): CommuteResponse { |
| | 370 | if (!this.authService.hasAuthority(RoleEnum.ROLE_PASSENGER)) throw UnauthorizedAccessException("Unauthorised role") |
| | 371 | val korisnik = this.authService.getAuthenticatedUser() |
| | 372 | val patnik = patnikRepository.findByKorisnik(korisnik) ?: throw NotFoundException("Korisnik") |
| | 373 | |
| | 374 | var bilet = biletRepository.findByIdAndPatnik(request.ticketId, patnik) ?: throw NotFoundException("Bilet") |
| | 375 | |
| | 376 | val instancaNaLinija = |
| | 377 | instancaNaLinijaRepository.findByIdOrNull(request.routeInstanceId) ?: throw NotFoundException("RouteInstanceId") |
| | 378 | val postojka = postojkaRepository.findByIdOrNull(request.stationId) ?: throw NotFoundException("StationId") |
| | 379 | |
| | 380 | val postojkaNaLinijaStart = |
| | 381 | postojkaNaLinijaRepository.findByLinijaAndPostojkaAndPravec(instancaNaLinija.linija, postojka, instancaNaLinija.pravec) |
| | 382 | ?: throw NotFoundException("Station not found") |
| | 383 | |
| | 384 | if (bilet.status == BiletEnum.INACTIVE) { |
| | 385 | bilet.status = BiletEnum.ACTIVE |
| | 386 | bilet.datumAktivacija = Timestamp.valueOf(LocalDateTime.now()) |
| | 387 | bilet = biletRepository.save(bilet) |
| | 388 | } |
| | 389 | |
| | 390 | val vozenje = |
| | 391 | Vozenje( |
| | 392 | id = 0L, |
| | 393 | startDate = Timestamp.valueOf(LocalDateTime.now()), |
| | 394 | endDate = null, |
| | 395 | status = VozenjeStatus.ACTIVE, |
| | 396 | patnik = patnik, |
| | 397 | postojkaNaLinijaStart = postojkaNaLinijaStart, |
| | 398 | instancaNaLinija = instancaNaLinija, |
| | 399 | bilet = bilet, |
| | 400 | ) |
| | 401 | return vozenjeRepository.save(vozenje).let { dtoMapper.toCommuteResponse(it) } |
| | 402 | } |
| | 403 | |
| | 404 | }}} |