= Фаза 4 - Процедури, функции и тригери == Линк до документацијата == Процедури - **`sp_buy_ticket`**: Процедурата го управува целосниот процес на купување билет. Прима идентификатор на корисник, проекција, седиште, начин на плаќање и вработен. Извршува осум последователни проверки — дали проекцијата постои, дали е во иднина, дали седиштето припаѓа на салата, дали е слободно — па потоа ја пресметува цената според типот на седиштето (Standard x1.0, VIP x2.0, Recliner x1.5, Couple x1.8, Disabled x0.7) и креира резервација, билет и плаќање. По успех прикажува детална порака, а при грешка целата трансакција се откажува. - **`sp_place_order`**: Процедурата го управува процесот на нарачување производи во киното. Прима идентификатор на корисник, производ, количина и вработен. Проверува дали производот постои и дали има доволно залиха, па креира нарачка во CinemaOrder, го внесува записот во Order_Product и ја намалува залихата за бараната количина. - **`pr_cancel_reservation`**: Процедурата го управува откажувањето на резервација. Прима идентификатор на резервација и се извршува во три чекори по строг редослед — прво ги брише билетите, потоа плаќањата и на крај го менува статусот на резервацијата во CANCELLED. - **`sp_submit_review`**: Процедурата го управува процесот на оставање рецензија за филм. Прима идентификатор на корисник, филм, оцена, коментар и датум. Пред внесување проверува дали корисникот го гледал филмот и дали проекцијата е завршена, дали веќе оставил рецензија за истиот филм и дали оцената е во опсег од 1 до 10. Доколку се поминати сите проверки, рецензијата се внесува во базата. - **`sp_make_reservation`**: Процедурата го управува резервирањето на седиште без непосредно плаќање. Прима идентификатор на корисник, проекција, седиште и вработен. Извршува проверки за постоење на проекцијата, корисникот и седиштето, слободност на седиштето и дали корисникот веќе има активна резервација. Цената ја пресметува преку fn_get_dynamic_price. Резервацијата се креира со статус PENDING, кој подоцна се потврдува со плаќање. == Функции - **`fn_get_dynamic_price`**: Функцијата пресметува динамична цена на билет според три множители — тип на седиште (Standard x1.0, VIP x2.0, Recliner x1.5, Couple x1.8, Disabled x0.7), пополнетост на салата над 60% (+20%) и групна набавка над четири карти за иста проекција (-20%). Прима идентификатор на проекција, тип на седиште и опционален идентификатор на корисник. - **`fn_hall_occupancy_report`**: Функцијата генерира визуелен извештај за состојбата на седиштата во салата за одредена проекција. За секој ред враќа визуелен приказ (○ слободно, X зафатено), број на слободни и зафатени места и процент на зафатеност. - **`fn_find_best_seat_position`**: Функцијата наоѓа N последователни слободни седишта во ист ред за одредена проекција. Ги скенира редовите по ред и ја враќа првата достапна група на бараниот број последователни места. Доколку не постои таква група, се враќа порака со препорака за помал број на седишта или друга проекција. == Тригери - **`trg_prevent_seat_double_booking`**: Тригерот спречува двојна резервација на исто седиште за иста проекција. Се активира пред секој INSERT во табелата Ticket и извршува две проверки — дали седиштето е веќе зафатено за таа проекција и дали седиштето воопшто припаѓа на салата. Доколку некоја проверка не помине, INSERT-от се откажува. - **`trg_prevent_showtime_overlap`**: Тригерот спречува временско преклопување на две проекции во иста сала. Се активира пред INSERT и UPDATE во табелата Showtime. Проверува дали во истата сала постои проекција чиј временски интервал се преклопува со новата, како и дали start_time е пред end_time. Доколку се детектира преклопување, операцијата се откажува со соодветна порака. - **`trg_check_reservation_before_showtime`**: Тригерот проверува дека датумот на резервација мора да биде пред датумот на проекцијата. Се активира пред INSERT и UPDATE во табелата Reservation. Го зема start_time на проекцијата и проверува дали reservation_date е пред него — доколку резервацијата е направена на ист ден или по почетокот на проекцијата, операцијата се откажува со порака која ги прикажува двата датуми. - **`trg_check_payment_after_reservation`**: Тригерот проверува дека датумот на плаќање не може да биде пред датумот на резервацијата. Се активира пред INSERT и UPDATE во табелата ReservationPayment. Го зема reservation_date на поврзаната резервација и проверува дали payment_date е поголем или еднаков на него — доколку плаќањето е внесено со датум пред резервацијата, операцијата се откажува со порака која ги прикажува двата датуми.