| 31 | | $$; |
| 32 | | }}} |
| 33 | | |
| 34 | | **Процедура за завршување на смена на возач** |
| 35 | | |
| 36 | | Процедурата проверува дали постои id-то на возачот, доколку не постои фрла соодветен исклучок. Потоа се проверува дали возачот има точно една активна смена која не е завршена. На крај се ажурира записот во табелата `Driver_Vehicle` на тој начин што се поставува тековното време во колоната `time_to`. Во апликацијата, оваа логика се повикува кога возачот сака да се одјави од системот, означувајќи го крајот на неговото работно време. |
| 37 | | |
| 38 | | {{{ |
| 39 | | create or replace procedure finish_shift( |
| 40 | | in driver_id int4 |
| 41 | | ) |
| 42 | | language plpgsql as |
| 43 | | $$ |
| 44 | | declare |
| 45 | | num_of_shifts int4; |
| 46 | | begin |
| 47 | | if not exists(select user_id from driver where user_id = driver_id) then |
| 48 | | raise exception 'Driver with id % does not exist', driver_id; |
| 49 | | end if; |
| 50 | | |
| 51 | | num_of_shifts := (select count(*) from driver_vehicle where id_driver = driver_id and time_to is null); |
| 52 | | |
| 53 | | if (num_of_shifts != 1) then |
| 54 | | raise exception 'Driver has not started a shift'; |
| 55 | | end if; |
| 56 | | |
| 57 | | update driver_vehicle |
| 58 | | set time_to=now() |
| 59 | | where id_driver = driver_id |
| 60 | | and time_to is null; |
| 61 | | commit; |
| 62 | | end; |
| 63 | | $$; |
| 64 | | }}} |
| 65 | | **Процедура за вработување на возач во компанија** |
| 66 | | |
| 67 | | Процедурата проверува дали id-то на возачот е валидно, доколку не постои фрла соодветен исклучок. Оваа процедура е дел од административниот модул на апликацијата и овозможува менаџирање на човечки ресурси, односно формално поврзување на возачот со конкретна такси компанија. |
| 68 | | |
| 69 | | {{{ |
| 70 | | create or replace procedure employ_driver(id_employee int, id_company int) |
| 71 | | language plpgsql |
| 72 | | as $$ |
| 73 | | begin |
| 74 | | if not exists ( |
| 75 | | select 1 |
| 76 | | from driver |
| 77 | | where user_id=id_employee) |
| 78 | | then |
| 79 | | raise exception 'Driver does not exist'; |
| 80 | | else |
| 81 | | insert into |
| 82 | | employmenthistory (employee_user_id, start_date, end_date, company_id) |
| 83 | | values (id_employee,current_date, null,id_company); |
| 84 | | end if; |
| 85 | | end; |
| 86 | | $$; |
| 87 | | }}} |
| 88 | | |
| 89 | | **Процедура за вработување на диспечер во компанија** |
| 90 | | |
| 91 | | Процедурата проверува дали id-то на диспечерот е валидно, доколку не постои фрла соодветен исклучок. Се користи за управување со кадар во рамките на компанијата. Ова овозможува диспечерот да добие овластување за креирање и испраќање на понуди во таа компанија. |
| 92 | | |
| 93 | | {{{ |
| 94 | | create or replace procedure employ_dispatcher(id_employee int, id_company int) |
| 95 | | language plpgsql |
| 96 | | as $$ |
| 97 | | begin |
| 98 | | if not exists ( |
| 99 | | select 1 |
| 100 | | from dispatcher |
| 101 | | where user_id=id_employee) |
| 102 | | then |
| 103 | | raise notice 'Dispatcher does not exist'; |
| 104 | | else |
| 105 | | insert into |
| 106 | | employmenthistory (employee_user_id, start_date, end_date, company_id) |
| 107 | | values (id_employee,current_date, null,id_company); |
| 108 | | end if; |
| 109 | | end; |
| 110 | | $$; |
| 111 | | }}} |
| 112 | | |
| 113 | | **Процедура за отпуштање/завршување на договор на возач во компанија** |
| 114 | | |
| 115 | | Процедурата прави две проверки. Првата проверка ја пребарува табелата Driver за id-то на возачот, доколку истото не постои се фрла соодветен исклучок. Потоа се проверува дали постои соодветен запис во табелата `EmploymentHistory` кој потврдува дека возачот е тековно вработен во компанијата. На крај се променува записот од табелата `EmploymentHistory` на тој начин што се става краен датум. Оваа процедура служи за прекинување на соработката, оневозможувајќи му на возачот понатаму да вози за таа компанија. |
| 116 | | |
| 117 | | {{{ |
| 118 | | create or replace procedure fire_driver(id_employee int, id_company int) |
| 119 | | language plpgsql |
| 120 | | as $$ |
| 121 | | begin |
| 122 | | if not exists ( |
| 123 | | select 1 |
| 124 | | from driver |
| 125 | | where user_id=id_employee) |
| 126 | | then |
| 127 | | raise exception 'Driver does not exist'; |
| 128 | | else |
| 129 | | if not exists ( |
| 130 | | select 1 |
| 131 | | from employmenthistory |
| 132 | | where employee_user_id=id_employee and end_date==null and company_id=id_company) |
| 133 | | then |
| 134 | | raise exception 'Driver does not have an employment'; |
| 135 | | else |
| 136 | | update employmenthistory |
| 137 | | set end_date=current_date |
| 138 | | where employee_user_id==id_employee and end_date==null and company_id=id_company; |
| 139 | | raise notice 'Driver is fired'; |
| 140 | | commit; |
| 141 | | end if; |
| 142 | | end if; |
| 143 | | end; |
| 144 | | $$; |
| 145 | | }}} |
| 146 | | |
| 147 | | **Процедура за отпуштање/завршување на договор на диспечер во компанија** |
| 148 | | |
| 149 | | Процедурата прави две проверки. Првата проверка ја пребарува табелата `Dispatcher` за id-то на диспечарот, доколку истото не постои се фрла соодветен исклучок. Потоа се проверува дали постои соодветен запис во табелата `EmploymentHistory` кој потврдува дека деспечерот е тековно вработен во компанијата. На крај се променува записот од табелата `EmploymentHistory` на тој начин што се става краен датум. Се користи за администрирање на правата на вработените, по извршувањето диспечерот ги губи сите привилегии за менаџирање со барањата на таа компанија. |
| 150 | | |
| 151 | | {{{ |
| 152 | | create or replace procedure fire_dispatcher(id_employee int, id_company int) |
| 153 | | language plpgsql |
| 154 | | as $$ |
| 155 | | begin |
| 156 | | if not exists ( |
| 157 | | select 1 |
| 158 | | from dispatcher |
| 159 | | where user_id=id_employee) |
| 160 | | then |
| 161 | | raise notice 'Dispatcher does not exist'; |
| 162 | | else |
| 163 | | if not exists( |
| 164 | | select 1 |
| 165 | | from employmenthistory |
| 166 | | where employee_user_id=id_employee and end_date==null and company_id=id_company) |
| 167 | | then |
| 168 | | raise exception 'Dispatcher does not have an employment'; |
| 169 | | else |
| 170 | | update employmenthistory |
| 171 | | set end_date=current_date |
| 172 | | where employee_user_id=id_employee and end_date==null and company_id=id_company; |
| 173 | | raise notice 'Dispatcher is fired'; |
| 174 | | commit; |
| 175 | | end if; |
| 176 | | end if; |
| 177 | | end; |
| 178 | | $$; |
| 179 | | }}} |
| 180 | | |
| 181 | | **Процедура за пишување на оцена** |
| 182 | | |
| 183 | | Оваа процедурата се повикува кога корисник испраќа свој коментар и рејтинг за возењето откако ќе пристигне на дестинацијата. Се проверува дали постои запис во табелата Ride за соодветните `id_ride` и `id_customer` доколку не постои се фрла исклучок `Customer can not give a rating on a ride they do not have.`. Имплементира логика за корисничка повратна информација, која е клучна за евалуација на квалитетот на такси услугата. |
| 184 | | |
| 185 | | {{{ |
| 186 | | create or replace procedure write_rating(rating numeric, comment text, id_ride int, id_customer int) |
| 187 | | language plpgsql |
| 188 | | as $$ |
| 189 | | begin |
| 190 | | if not exists( |
| 191 | | select 1 |
| 192 | | from Ride r |
| 193 | | join Request req on r.request_id=req.id |
| 194 | | where r.id=id_ride and req.customer_user_id=id_customer |
| 195 | | ) |
| 196 | | then |
| 197 | | raise exception 'Customer can not give a rating on a ride they do not have.'; |
| 198 | | end if; |
| 199 | | insert into review (rating, comment, ride_id, customer_user_id) |
| 200 | | values (write_rating.rating,write_rating.comment,id_ride,id_customer); |
| 201 | | end; |
| 202 | | $$; |
| 203 | | }}} |
| 204 | | |
| 205 | | **Процедура за испраќање порака** |
| 206 | | |
| 207 | | Пораките можат да бидат испратени од возачот или патникот и се однесуваат на едно возење. Доколку не постои возење за соодветните `id_ride` и `id_user` се фрла исклучок `User can not write a chat for a ride they do not have.`. Оваа процедура е главна во системот за чет помеѓу патникот и возачот за време на реализацијата на услугата. |
| 208 | | |
| 209 | | {{{ |
| 210 | | create or replace procedure write_chat(new_message text, id_ride int, id_user int) |
| 211 | | language plpgsql |
| 212 | | as $$ |
| 213 | | begin |
| 214 | | if not exists( |
| 215 | | select 1 |
| 216 | | from Ride r |
| 217 | | join Request req on r.request_id=req.id |
| 218 | | where r.id=id_ride and req.customer_user_id=id_user |
| 219 | | ) |
| 220 | | then |
| 221 | | raise exception 'User can not write a chat for a ride they do not have.'; |
| 222 | | end if; |
| 223 | | insert into chatmessage(message, user_id_from, ride_id) |
| 224 | | values (new_message,id_user,id_ride); |
| 225 | | end; |
| 226 | | $$; |
| 227 | | }}} |
| 228 | | |
| 229 | | **Процедура за поднесување пријава** |
| 230 | | |
| 231 | | Оваа процедура се повикува кога корисниците поднесуваат пријава за време на возењето. Тоа може да биде некоја поплака од типот брзо возење или скршнување од патот. Доколку не постои возење за соодветните `id_ride` и `user_id` се фрла исклучок `Customer can not write a report on a ride they do not have.`. Се користи во модулот за безбедност и заштита на корисниците, овозможувајќи брза реакција на поддршката. |
| 232 | | |
| 233 | | {{{ |
| 234 | | create or replace procedure write_report(id_ride int, user_id int, new_message text, new_title text,temp_latitude float, temp_long float, new_reason text) |
| 235 | | language plpgsql |
| 236 | | as $$ |
| 237 | | begin |
| 238 | | if not exists( |
| 239 | | select 1 |
| 240 | | from Ride r |
| 241 | | join Request req on r.request_id=req.id |
| 242 | | where r.id=id_ride and req.customer_user_id=user_id |
| 243 | | ) |
| 244 | | then |
| 245 | | raise exception 'Customer can not write a report on a ride they do not have.'; |
| 246 | | end if; |
| 247 | | insert into report(ride_id, customer_user_id, message, title, latitude, longitude, reason) |
| 248 | | values (id_ride,user_id,new_message,new_title,temp_latitude,temp_long,new_reason); |
| 249 | | end; |
| | 254 | **Процедура за вработување на возач во компанија** |
| | 255 | |
| | 256 | Процедурата проверува дали id-то на возачот е валидно, доколку не постои фрла соодветен исклучок. Оваа процедура е дел од административниот модул на апликацијата и овозможува менаџирање на човечки ресурси, односно формално поврзување на возачот со конкретна такси компанија. |
| | 257 | |
| | 258 | {{{ |
| | 259 | create or replace procedure employ_driver(id_employee int, id_company int) |
| | 260 | language plpgsql |
| | 261 | as $$ |
| | 262 | begin |
| | 263 | if not exists ( |
| | 264 | select 1 |
| | 265 | from driver |
| | 266 | where user_id=id_employee) |
| | 267 | then |
| | 268 | raise exception 'Driver does not exist'; |
| | 269 | else |
| | 270 | insert into |
| | 271 | employmenthistory (employee_user_id, start_date, end_date, company_id) |
| | 272 | values (id_employee,current_date, null,id_company); |
| | 273 | end if; |
| | 274 | end; |
| | 275 | $$; |
| | 276 | }}} |
| | 277 | |
| | 278 | **Процедура за вработување на диспечер во компанија** |
| | 279 | |
| | 280 | Процедурата проверува дали id-то на диспечерот е валидно, доколку не постои фрла соодветен исклучок. Се користи за управување со кадар во рамките на компанијата. Ова овозможува диспечерот да добие овластување за креирање и испраќање на понуди во таа компанија. |
| | 281 | |
| | 282 | {{{ |
| | 283 | create or replace procedure employ_dispatcher(id_employee int, id_company int) |
| | 284 | language plpgsql |
| | 285 | as $$ |
| | 286 | begin |
| | 287 | if not exists ( |
| | 288 | select 1 |
| | 289 | from dispatcher |
| | 290 | where user_id=id_employee) |
| | 291 | then |
| | 292 | raise notice 'Dispatcher does not exist'; |
| | 293 | else |
| | 294 | insert into |
| | 295 | employmenthistory (employee_user_id, start_date, end_date, company_id) |
| | 296 | values (id_employee,current_date, null,id_company); |
| | 297 | end if; |
| | 298 | end; |
| | 299 | $$; |
| | 300 | }}} |
| | 301 | |
| | 302 | **Процедура за отпуштање/завршување на договор на возач во компанија** |
| | 303 | |
| | 304 | Процедурата прави две проверки. Првата проверка ја пребарува табелата Driver за id-то на возачот, доколку истото не постои се фрла соодветен исклучок. Потоа се проверува дали постои соодветен запис во табелата `EmploymentHistory` кој потврдува дека возачот е тековно вработен во компанијата. На крај се променува записот од табелата `EmploymentHistory` на тој начин што се става краен датум. Оваа процедура служи за прекинување на соработката, оневозможувајќи му на возачот понатаму да вози за таа компанија. |
| | 305 | |
| | 306 | {{{ |
| | 307 | create or replace procedure fire_driver(id_employee int, id_company int) |
| | 308 | language plpgsql |
| | 309 | as $$ |
| | 310 | begin |
| | 311 | if not exists ( |
| | 312 | select 1 |
| | 313 | from driver |
| | 314 | where user_id=id_employee) |
| | 315 | then |
| | 316 | raise exception 'Driver does not exist'; |
| | 317 | else |
| | 318 | if not exists ( |
| | 319 | select 1 |
| | 320 | from employmenthistory |
| | 321 | where employee_user_id=id_employee and end_date==null and company_id=id_company) |
| | 322 | then |
| | 323 | raise exception 'Driver does not have an employment'; |
| | 324 | else |
| | 325 | update employmenthistory |
| | 326 | set end_date=current_date |
| | 327 | where employee_user_id==id_employee and end_date==null and company_id=id_company; |
| | 328 | raise notice 'Driver is fired'; |
| | 329 | commit; |
| | 330 | end if; |
| | 331 | end if; |
| | 332 | end; |
| | 333 | $$; |
| | 334 | }}} |
| | 335 | |
| | 336 | **Процедура за отпуштање/завршување на договор на диспечер во компанија** |
| | 337 | |
| | 338 | Процедурата прави две проверки. Првата проверка ја пребарува табелата `Dispatcher` за id-то на диспечарот, доколку истото не постои се фрла соодветен исклучок. Потоа се проверува дали постои соодветен запис во табелата `EmploymentHistory` кој потврдува дека деспечерот е тековно вработен во компанијата. На крај се променува записот од табелата `EmploymentHistory` на тој начин што се става краен датум. Се користи за администрирање на правата на вработените, по извршувањето диспечерот ги губи сите привилегии за менаџирање со барањата на таа компанија. |
| | 339 | |
| | 340 | {{{ |
| | 341 | create or replace procedure fire_dispatcher(id_employee int, id_company int) |
| | 342 | language plpgsql |
| | 343 | as $$ |
| | 344 | begin |
| | 345 | if not exists ( |
| | 346 | select 1 |
| | 347 | from dispatcher |
| | 348 | where user_id=id_employee) |
| | 349 | then |
| | 350 | raise notice 'Dispatcher does not exist'; |
| | 351 | else |
| | 352 | if not exists( |
| | 353 | select 1 |
| | 354 | from employmenthistory |
| | 355 | where employee_user_id=id_employee and end_date==null and company_id=id_company) |
| | 356 | then |
| | 357 | raise exception 'Dispatcher does not have an employment'; |
| | 358 | else |
| | 359 | update employmenthistory |
| | 360 | set end_date=current_date |
| | 361 | where employee_user_id=id_employee and end_date==null and company_id=id_company; |
| | 362 | raise notice 'Dispatcher is fired'; |
| | 363 | commit; |
| | 364 | end if; |
| | 365 | end if; |
| | 366 | end; |
| | 367 | $$; |
| | 368 | }}} |
| | 369 | |
| | 370 | **Процедура за пишување на оцена** |
| | 371 | |
| | 372 | Оваа процедурата се повикува кога корисник испраќа свој коментар и рејтинг за возењето откако ќе пристигне на дестинацијата. Се проверува дали постои запис во табелата Ride за соодветните `id_ride` и `id_customer` доколку не постои се фрла исклучок `Customer can not give a rating on a ride they do not have.`. Имплементира логика за корисничка повратна информација, која е клучна за евалуација на квалитетот на такси услугата. |
| | 373 | |
| | 374 | {{{ |
| | 375 | create or replace procedure write_rating(rating numeric, comment text, id_ride int, id_customer int) |
| | 376 | language plpgsql |
| | 377 | as $$ |
| | 378 | begin |
| | 379 | if not exists( |
| | 380 | select 1 |
| | 381 | from Ride r |
| | 382 | join Request req on r.request_id=req.id |
| | 383 | where r.id=id_ride and req.customer_user_id=id_customer |
| | 384 | ) |
| | 385 | then |
| | 386 | raise exception 'Customer can not give a rating on a ride they do not have.'; |
| | 387 | end if; |
| | 388 | insert into review (rating, comment, ride_id, customer_user_id) |
| | 389 | values (write_rating.rating,write_rating.comment,id_ride,id_customer); |
| | 390 | end; |
| | 391 | $$; |
| | 392 | }}} |
| | 393 | |
| | 394 | **Процедура за испраќање порака** |
| | 395 | |
| | 396 | Пораките можат да бидат испратени од возачот или патникот и се однесуваат на едно возење. Доколку не постои возење за соодветните `id_ride` и `id_user` се фрла исклучок `User can not write a chat for a ride they do not have.`. Оваа процедура е главна во системот за чет помеѓу патникот и возачот за време на реализацијата на услугата. |
| | 397 | |
| | 398 | {{{ |
| | 399 | create or replace procedure write_chat(new_message text, id_ride int, id_user int) |
| | 400 | language plpgsql |
| | 401 | as $$ |
| | 402 | begin |
| | 403 | if not exists( |
| | 404 | select 1 |
| | 405 | from Ride r |
| | 406 | join Request req on r.request_id=req.id |
| | 407 | where r.id=id_ride and req.customer_user_id=id_user |
| | 408 | ) |
| | 409 | then |
| | 410 | raise exception 'User can not write a chat for a ride they do not have.'; |
| | 411 | end if; |
| | 412 | insert into chatmessage(message, user_id_from, ride_id) |
| | 413 | values (new_message,id_user,id_ride); |
| | 414 | end; |
| | 415 | $$; |
| | 416 | }}} |
| | 417 | |
| | 418 | **Процедура за поднесување пријава** |
| | 419 | |
| | 420 | Оваа процедура се повикува кога корисниците поднесуваат пријава за време на возењето. Тоа може да биде некоја поплака од типот брзо возење или скршнување од патот. Доколку не постои возење за соодветните `id_ride` и `user_id` се фрла исклучок `Customer can not write a report on a ride they do not have.`. Се користи во модулот за безбедност и заштита на корисниците, овозможувајќи брза реакција на поддршката. |
| | 421 | |
| | 422 | {{{ |
| | 423 | create or replace procedure write_report(id_ride int, user_id int, new_message text, new_title text,temp_latitude float, temp_long float, new_reason text) |
| | 424 | language plpgsql |
| | 425 | as $$ |
| | 426 | begin |
| | 427 | if not exists( |
| | 428 | select 1 |
| | 429 | from Ride r |
| | 430 | join Request req on r.request_id=req.id |
| | 431 | where r.id=id_ride and req.customer_user_id=user_id |
| | 432 | ) |
| | 433 | then |
| | 434 | raise exception 'Customer can not write a report on a ride they do not have.'; |
| | 435 | end if; |
| | 436 | insert into report(ride_id, customer_user_id, message, title, latitude, longitude, reason) |
| | 437 | values (id_ride,user_id,new_message,new_title,temp_latitude,temp_long,new_reason); |
| | 438 | end; |
| | 439 | $$; |
| | 440 | }}} |
| | 441 | |
| | 442 | |
| | 443 | |
| 675 | | }}} |
| 676 | | |
| 677 | | **Функција и тригер за спречување на возење со неважечка возачка дозвола** |
| 678 | | |
| 679 | | Функцијата го пребарува датумот на истекување на возачката дозвола за соодветниот возач преку поврзување на табелите `Driver` и `DriverLicense`. Доколку дозволата е истечена во однос на тековниот датум, се фрла соодветен исклучок, а тригерот се извршува пред внес на нов запис во табелата `Ride`. Целта на оваа рестрикција е правна и сигурносна заштита на платформата, осигурувајќи дека само лиценцирани возачи можат да превезуваат патници. |
| 680 | | |
| 681 | | {{{ |
| 682 | | create or replace function prevent_expired_license_ride() |
| 683 | | returns trigger as |
| 684 | | $prevent_expired_license_ride$ |
| 685 | | declare |
| 686 | | exp_date date; |
| 687 | | begin |
| 688 | | select dl.expire_date |
| 689 | | into exp_date |
| 690 | | from driver d |
| 691 | | join driverlicense dl on d.driver_license_id = dl.id |
| 692 | | where d.user_id = new.driver_user_id; |
| 693 | | |
| 694 | | if exp_date is not null and exp_date < current_date then |
| 695 | | raise exception 'Driver license expired'; |
| 696 | | end if; |
| 697 | | |
| 698 | | return new; |
| 699 | | end; |
| 700 | | $prevent_expired_license_ride$ language plpgsql; |
| 701 | | create or replace trigger prevent_expired_license_ride |
| 702 | | before insert |
| 703 | | on ride |
| 704 | | for each row |
| 705 | | execute function prevent_expired_license_ride(); |
| 706 | | }}} |
| 707 | | |
| 708 | | **Функција и тригер за спречување на промена на статус на завршена понуда** |
| 709 | | |
| 710 | | Функцијата проверува дали претходниот статус на понудата бил `completed`, при што фрла соодветен исклучок доколку се направи обид за негова промена во било кој друг статус. Тригерот се извршува пред ажурирање на запис во табелата `Offer`. Ова ја гарантира веродостојноста на архивските податоци во системот кои подоцна се користат за генерирање извештаи. |
| 711 | | |
| 712 | | {{{ |
| 713 | | create or replace function prevent_completed_offer_downgrade() |
| 714 | | returns trigger as |
| 715 | | $prevent_completed_offer_downgrade$ |
| 716 | | begin |
| 717 | | if old.status = 'completed' |
| 718 | | and new.status <> 'completed' then |
| 719 | | raise exception 'Completed offer cannot change status'; |
| 720 | | end if; |
| 721 | | |
| 722 | | return new; |
| 723 | | end; |
| 724 | | $prevent_completed_offer_downgrade$ language plpgsql; |
| 725 | | create or replace trigger prevent_completed_offer_downgrade |
| 726 | | before update |
| 727 | | on offer |
| 728 | | for each row |
| 729 | | execute function prevent_completed_offer_downgrade(); |
| 730 | | }}} |
| 731 | | |
| 732 | | ** Функција и тригер за контрола на времето на важност на понудата ** |
| 733 | | |
| 734 | | Оваа функција враќа тригер кој спречува прифаќање на понуди кои се постари од 5 минути од моментот на нивното креирање. Доколку се направи обид за промена на статусот од `pending` во `accepted` по истекот на овој рок, статусот на понудата автоматски се менува во `expired` и истата не може да биде прифатена. Оваа логика овозможува динамичност на пазарот, со цел возачите и диспечерите да не бидат долго блокирани чекајќи одговор од патникот. |
| 735 | | |
| 736 | | {{{ |
| 737 | | create or replace function enforce_offer_validity() |
| 738 | | returns trigger as |
| 739 | | $enforce_offer_validity$ |
| 740 | | begin |
| 741 | | if OLD.status = 'pending' and NEW.status = 'accepted' then |
| 742 | | if (NOW() - OLD.created_at) > interval '5 minutes' then |
| 743 | | NEW.status := 'expired'; |
| 744 | | raise notice 'Offer % has expired and cannot be accepted.', OLD.id; |
| 745 | | return NEW; |
| 746 | | end if; |
| 747 | | end if; |
| 748 | | |
| 749 | | return NEW; |
| 750 | | end; |
| 751 | | $enforce_offer_validity$ language plpgsql; |
| 752 | | |
| 753 | | create trigger trg_enforce_offer_validity |
| 754 | | before update on offer |
| 755 | | for each row |
| 756 | | execute function enforce_offer_validity(); |
| | 721 | |
| | 722 | |
| | 723 | **Функција и тригер за проверка на достапност на возач** |
| | 724 | |
| | 725 | Функцијата `ride_assign` враќа тригер кој фрла исклучок во случај возачот да е зафатен со друго возење во моментот на доделување на возач. Тригерот се извршува пред внес на запис во табелата `Ride`. Во контекст на бизнис логиката, ова спречува преклопување на возењата и гарантира дека еден возач не може физички да извршува две патувања истовремено. |
| | 726 | |
| | 727 | {{{ |
| | 728 | create or replace function ride_assign() returns trigger as |
| | 729 | $ride_assign$ |
| | 730 | begin |
| | 731 | if exists(select * from ride where ride.status = 'in_progress' and ride.driver_user_id = NEW.driver_user_id) then |
| | 732 | raise exception 'Driver not free'; |
| | 733 | end if; |
| | 734 | return NEW; |
| | 735 | end; |
| | 736 | $ride_assign$ language plpgsql; |
| | 737 | |
| | 738 | create trigger ride_assign before insert on ride |
| | 739 | for each row execute function ride_assign(); |
| | 740 | }}} |
| | 741 | |
| | 742 | ** Функција и тригер за спречување на манипулација со цената ** |
| | 743 | |
| | 744 | Функцијата враќа тригер кој спречува промена на цената на понудата откако истата ќе добие статус `accepted` или `completed`. Дополнително, се прави проверка дали внесената цена е поголема од нула, при што се фрла соодветен исклучок доколку овие услови не се исполнети. Ова директно ја заштитува финансиската сигурност во системот и спречува неовластени или измамнички промени на трошоците по договарањето. |
| | 745 | |
| | 746 | {{{ |
| | 747 | create or replace function prevent_price_manipulation() |
| | 748 | returns trigger as |
| | 749 | $prevent_price_manipulation$ |
| | 750 | begin |
| | 751 | if OLD.status in ('accepted', 'completed') and NEW.price <> OLD.price then |
| | 752 | raise exception 'Price cannot be modified once the offer is accepted or completed. Current status: %', OLD.status; |
| | 753 | end if; |
| | 754 | |
| | 755 | if NEW.price <= 0 then |
| | 756 | raise exception 'Price must be a positive value'; |
| | 757 | end if; |
| | 758 | |
| | 759 | return NEW; |
| | 760 | end; |
| | 761 | $prevent_price_manipulation$ language plpgsql; |
| | 762 | |
| | 763 | create trigger prevent_price_manipulation |
| | 764 | before update on offer |
| | 765 | for each row |
| | 766 | execute function prevent_price_manipulation(); |
| | 767 | }}} |
| | 768 | |
| | 769 | ** Функција и тригер за контрола на времето на важност на понудата ** |
| | 770 | |
| | 771 | Оваа функција враќа тригер кој спречува прифаќање на понуди кои се постари од 5 минути од моментот на нивното креирање. Доколку се направи обид за промена на статусот од `pending` во `accepted` по истекот на овој рок, статусот на понудата автоматски се менува во `expired` и истата не може да биде прифатена. Оваа логика овозможува динамичност на пазарот, со цел возачите и диспечерите да не бидат долго блокирани чекајќи одговор од патникот. |
| | 772 | |
| | 773 | {{{ |
| | 774 | create or replace function enforce_offer_validity() |
| | 775 | returns trigger as |
| | 776 | $enforce_offer_validity$ |
| | 777 | begin |
| | 778 | if OLD.status = 'pending' and NEW.status = 'accepted' then |
| | 779 | if (NOW() - OLD.created_at) > interval '5 minutes' then |
| | 780 | NEW.status := 'expired'; |
| | 781 | raise notice 'Offer % has expired and cannot be accepted.', OLD.id; |
| | 782 | return NEW; |
| | 783 | end if; |
| | 784 | end if; |
| | 785 | |
| | 786 | return NEW; |
| | 787 | end; |
| | 788 | $enforce_offer_validity$ language plpgsql; |
| | 789 | |
| | 790 | create trigger trg_enforce_offer_validity |
| | 791 | before update on offer |
| | 792 | for each row |
| | 793 | execute function enforce_offer_validity(); |
| | 794 | }}} |