| 698 | | [[Image("Screenshot 2026-05-20 171652.png", 300px)]] |
| 699 | | |
| 700 | | [[Image("Screenshot 2026-05-20 171658.png", 300px)]] |
| 701 | | |
| | 673 | {{{ |
| | 674 | CREATE OR REPLACE FUNCTION get_trip_revenue_efficiency(p_trip_id INT) |
| | 675 | RETURNS TEXT AS $$ |
| | 676 | DECLARE |
| | 677 | v_capacity INT; |
| | 678 | v_sold_count INT; |
| | 679 | v_total_revenue NUMERIC; |
| | 680 | v_occupancy_pct NUMERIC; |
| | 681 | v_rev_per_seat NUMERIC; |
| | 682 | v_result TEXT; |
| | 683 | BEGIN |
| | 684 | SELECT t.capacity INTO v_capacity |
| | 685 | FROM "Train Trip" tt |
| | 686 | JOIN Train t ON tt.Traintrain_id = t.train_id |
| | 687 | WHERE tt.trip_id = p_trip_id; |
| | 688 | |
| | 689 | SELECT COUNT(*), COALESCE(SUM(price), 0) |
| | 690 | INTO v_sold_count, v_total_revenue |
| | 691 | FROM Ticket |
| | 692 | WHERE "Train Triptrip_id" = p_trip_id; |
| | 693 | |
| | 694 | IF v_capacity > 0 THEN |
| | 695 | v_occupancy_pct := (v_sold_count::NUMERIC / v_capacity) * 100; |
| | 696 | v_rev_per_seat := v_total_revenue / v_capacity; |
| | 697 | ELSE |
| | 698 | RETURN 'Error: Train has no capacity'; |
| | 699 | END IF; |
| | 700 | |
| | 701 | IF v_occupancy_pct >= 85 THEN |
| | 702 | v_result := 'High Demand (' || ROUND(v_occupancy_pct, 1) || '%)'; |
| | 703 | ELSIF v_occupancy_pct >= 50 THEN |
| | 704 | v_result := 'Optimal (' || ROUND(v_occupancy_pct, 1) || '%)'; |
| | 705 | ELSE |
| | 706 | v_result := 'Low Efficiency (' || ROUND(v_occupancy_pct, 1) || '%)'; |
| | 707 | END IF; |
| | 708 | |
| | 709 | RETURN v_result || ' | Rev/Seat: ' || ROUND(v_rev_per_seat, 2); |
| | 710 | END; |
| | 711 | $$ LANGUAGE plpgsql; |
| | 712 | |
| | 713 | SELECT |
| | 714 | tt.trip_id, |
| | 715 | r.route_name, |
| | 716 | tt.departure_time, |
| | 717 | get_trip_revenue_efficiency(tt.trip_id) AS performance_report |
| | 718 | FROM "Train Trip" tt |
| | 719 | JOIN Route r ON tt.Routeroute_id = r.route_id |
| | 720 | WHERE tt.trip_status = 'Completed' |
| | 721 | ORDER BY tt.departure_time DESC |
| | 722 | LIMIT 150; |
| | 723 | }}} |
| 712 | | [[Image("Screenshot 2026-05-20 172105.png", 300px)]] |
| 713 | | |
| 714 | | Оваа функција ја наоѓа најпрофитабилната рута во системот. Го пресметува вкупниот приход од билети за секоја рута и ја враќа онаа со најголем приход, заедно со сумата. Во проектот се користи за анализа на бизнис перформанси и идентификација на најисплатливи линии. |
| 715 | | |
| 716 | | |
| 717 | | |
| 718 | | |
| 719 | | |
| 720 | | |
| 721 | | |
| | 749 | {{{ |
| | 750 | CREATE OR REPLACE FUNCTION get_most_profitable_route() |
| | 751 | RETURNS TEXT AS $$ |
| | 752 | DECLARE |
| | 753 | v_route_name VARCHAR; |
| | 754 | v_total_revenue NUMERIC; |
| | 755 | BEGIN |
| | 756 | SELECT |
| | 757 | r.route_name, |
| | 758 | COALESCE(SUM(t.price), 0) |
| | 759 | INTO |
| | 760 | v_route_name, |
| | 761 | v_total_revenue |
| | 762 | FROM Route r |
| | 763 | JOIN "Train Trip" tt |
| | 764 | ON r.route_id = tt.Routeroute_id |
| | 765 | JOIN Ticket t |
| | 766 | ON tt.trip_id = t."Train Triptrip_id" |
| | 767 | GROUP BY r.route_id, r.route_name |
| | 768 | ORDER BY SUM(t.price) DESC |
| | 769 | LIMIT 1; |
| | 770 | |
| | 771 | RETURN |
| | 772 | 'Most Profitable Route: ' || v_route_name || |
| | 773 | ' | Total Revenue: ' || ROUND(v_total_revenue, 2); |
| | 774 | END; |
| | 775 | $$ LANGUAGE plpgsql; |
| | 776 | |
| | 777 | SELECT get_most_profitable_route(); |
| | 778 | }}} |
| | 779 | Оваа функција ја наоѓа најпрофитабилната рута во системот. Го пресметува вкупниот приход од билети за секоја рута и ја враќа онаа со најголем приход, заедно со сумата. Cе користи за анализа на бизнис перформанси и идентификација на најисплатливи линии. |
| | 780 | |
| | 781 | === Функција 7 : check_frequent_traveler |
| | 782 | |
| | 783 | {{{ |
| | 784 | CREATE OR REPLACE FUNCTION check_frequent_traveler(p_passenger_id INT) |
| | 785 | RETURNS TEXT AS $$ |
| | 786 | DECLARE |
| | 787 | v_ticket_count INT; |
| | 788 | v_full_name VARCHAR; |
| | 789 | BEGIN |
| | 790 | |
| | 791 | SELECT p.first_name || ' ' || p.last_name |
| | 792 | INTO v_full_name |
| | 793 | FROM Passenger pass |
| | 794 | JOIN Person p ON pass.PersonEMBG = p.EMBG |
| | 795 | WHERE pass.passenger_id = p_passenger_id |
| | 796 | LIMIT 1; |
| | 797 | |
| | 798 | SELECT COUNT(t.ticket_id) |
| | 799 | INTO v_ticket_count |
| | 800 | FROM Ticket t |
| | 801 | JOIN Payment pay ON t.Paymentpayment_id = pay.payment_id |
| | 802 | JOIN Reservation r ON pay.Reservationreservation_id = r.reservation_id |
| | 803 | WHERE r.Passengerpassenger_id = p_passenger_id; |
| | 804 | |
| | 805 | IF v_ticket_count >= 20 THEN |
| | 806 | RETURN v_full_name || ' is a VIP Frequent Traveler with ' || v_ticket_count || ' trips.'; |
| | 807 | ELSIF v_ticket_count >= 10 THEN |
| | 808 | RETURN v_full_name || ' is a Frequent Traveler with ' || v_ticket_count || ' trips.'; |
| | 809 | ELSIF v_ticket_count > 0 THEN |
| | 810 | RETURN v_full_name || ' is an Occasional Traveler with ' || v_ticket_count || ' trips.'; |
| | 811 | ELSE |
| | 812 | RETURN v_full_name || ' has no trips.'; |
| | 813 | END IF; |
| | 814 | END; |
| | 815 | $$ LANGUAGE plpgsql; |
| | 816 | |
| | 817 | SELECT check_frequent_traveler(800); |
| | 818 | }}} |
| | 819 | Оваа функција проверува колку патувања има направено одреден патник во системот. Го пресметува вкупниот број на купени билети поврзани со неговите резервации и врз основа на тоа го класифицира како VIP Frequent Traveler, Frequent Traveler, Occasional Traveler или патник без патувања. Cе користи за анализа на активноста и лојалноста на патниците, како и за идентификација на најактивните корисници. |
| | 820 | |
| | 821 | === Функција 8 : get_revenue_by_period |
| | 822 | |
| | 823 | {{{ |
| | 824 | CREATE OR REPLACE FUNCTION get_revenue_by_period( |
| | 825 | p_start_date DATE, |
| | 826 | p_end_date DATE |
| | 827 | ) |
| | 828 | RETURNS TEXT AS $$ |
| | 829 | DECLARE |
| | 830 | v_total_tickets INT; |
| | 831 | v_total_revenue NUMERIC; |
| | 832 | BEGIN |
| | 833 | SELECT |
| | 834 | COUNT(*), |
| | 835 | COALESCE(SUM(t.price), 0) |
| | 836 | INTO |
| | 837 | v_total_tickets, |
| | 838 | v_total_revenue |
| | 839 | FROM Ticket t |
| | 840 | JOIN "Train Trip" tt |
| | 841 | ON t."Train Triptrip_id" = tt.trip_id |
| | 842 | WHERE tt.departure_time::DATE |
| | 843 | BETWEEN p_start_date AND p_end_date; |
| | 844 | |
| | 845 | RETURN |
| | 846 | 'Period: ' || p_start_date || ' to ' || p_end_date || |
| | 847 | ' | Tickets Sold: ' || v_total_tickets || |
| | 848 | ' | Total Revenue: ' || ROUND(v_total_revenue, 2); |
| | 849 | END; |
| | 850 | $$ LANGUAGE plpgsql; |
| | 851 | |
| | 852 | SELECT get_revenue_by_period('2025-01-01', '2026-03-31'); |
| | 853 | }}} |
| | 854 | Оваа функција ги пресметува вкупниот број на продадени билети и вкупниот приход остварен во одреден временски период. Ги анализира билетите поврзани со патувања чие време на поаѓање се наоѓа помеѓу внесените датуми и враќа информација за бројот на продадени билети и остварениот приход. Cе користи за финансиска анализа, следење на продажбата и проценка на приходите во одреден период. |
| | 855 | |
| | 856 | |
| | 857 | |
| | 858 | |
| | 859 | |
| | 860 | |
| | 861 | |
| | 862 | |
| | 863 | |