Changes between Version 4 and Version 5 of DatabaseCreation


Ignore:
Timestamp:
09/14/26 21:52:28 (12 days ago)
Author:
231075
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DatabaseCreation

    v4 v5  
    248248Табелата е дополнително поврзана со `Management_User`, `Review` и `Vendor_User` преку странски клучеви.
    249249
     250== Views ==
     251
     252За почесто користените прикази и аналитички податоци се дефинирани PostgreSQL views. Тие ги обединуваат податоците од повеќе поврзани табели и овозможуваат поедноставен пристап до информации за проекти, договори, буџети, оценки, спорови и претплати.
     253
     254Целосната скрипта е достапна во:
     255
     256* [attachment:views.sql views.sql]
     257
     258=== Проекти по Vendor и Client ===
     259
     260Погледот `vw_projects_per_vendor` ги прикажува сите проекти поврзани со одреден vendor, заедно со статусот, периодот и буџетот:
     261
     262{{{#!sql
     263CREATE OR REPLACE VIEW vw_projects_per_vendor AS
     264SELECT v.vendor_id,
     265v.agency_name,
     266p.project_id,
     267p.project_name,
     268ps.status_name,
     269p.start_date,
     270p.end_date,
     271p.budget,
     272cvc.currency_code
     273FROM Project p
     274JOIN Client_Vendor_Contract cvc
     275ON cvc.contract_id = p.contract_id
     276JOIN Vendor v
     277ON v.vendor_id = cvc.vendor_id
     278JOIN Project_Status ps
     279ON ps.status_id = p.status_id
     280ORDER BY v.agency_name, ps.status_name, p.project_name;
     281}}}
     282
     283Соодветниот поглед за клиентите е `vw_projects_per_client`:
     284
     285{{{#!sql
     286CREATE OR REPLACE VIEW vw_projects_per_client AS
     287SELECT c.client_id,
     288c.company_name,
     289p.project_id,
     290p.project_name,
     291ps.status_name,
     292p.start_date,
     293p.end_date,
     294p.budget,
     295cvc.currency_code
     296FROM Project p
     297JOIN Client_Vendor_Contract cvc
     298ON cvc.contract_id = p.contract_id
     299JOIN Client c
     300ON c.client_id = cvc.client_id
     301JOIN Project_Status ps
     302ON ps.status_id = p.status_id
     303ORDER BY c.company_name, ps.status_name, p.project_name;
     304}}}
     305
     306=== Буџети по Vendor и Client ===
     307
     308За аналитички приказ на вкупниот број на проекти и нивниот буџет се користат `vw_budget_per_vendor` и `vw_budget_per_client`.
     309
     310{{{#!sql
     311CREATE OR REPLACE VIEW vw_budget_per_vendor AS
     312SELECT v.vendor_id,
     313v.agency_name,
     314cvc.currency_code,
     315COUNT(p.project_id) AS project_count,
     316SUM(p.budget)       AS total_budget
     317FROM Project p
     318JOIN Client_Vendor_Contract cvc
     319ON cvc.contract_id = p.contract_id
     320JOIN Vendor v
     321ON v.vendor_id = cvc.vendor_id
     322GROUP BY v.vendor_id, v.agency_name, cvc.currency_code
     323ORDER BY v.agency_name, cvc.currency_code;
     324}}}
     325
     326{{{#!sql
     327CREATE OR REPLACE VIEW vw_budget_per_client AS
     328SELECT c.client_id,
     329c.company_name,
     330cvc.currency_code,
     331COUNT(p.project_id) AS project_count,
     332SUM(p.budget)       AS total_budget
     333FROM Project p
     334JOIN Client_Vendor_Contract cvc
     335ON cvc.contract_id = p.contract_id
     336JOIN Client c
     337ON c.client_id = cvc.client_id
     338GROUP BY c.client_id, c.company_name, cvc.currency_code
     339ORDER BY c.company_name, cvc.currency_code;
     340}}}
     341
     342Групирањето се врши и според `currency_code`, со што буџетите во различни валути не се собираат во една вредност.
     343
     344=== Клиенти по индустрија ===
     345
     346`vw_clients_per_industry` овозможува приказ на клиентските компании групирани според нивната индустрија:
     347
     348{{{#!sql
     349CREATE OR REPLACE VIEW vw_clients_per_industry AS
     350SELECT i.industry_id,
     351i.industry_name,
     352c.client_id,
     353c.company_name,
     354c.contact_email
     355FROM Client c
     356JOIN Industry i
     357ON i.industry_id = c.industry_id
     358ORDER BY i.industry_name, c.company_name;
     359}}}
     360
     361=== Просечна оценка по Vendor ===
     362
     363За секој vendor се пресметува просечна оценка од сите `Review_Score` записи за неговите проекти:
     364
     365{{{#!sql
     366CREATE OR REPLACE VIEW vw_avg_rating_per_vendor AS
     367SELECT v.vendor_id,
     368v.agency_name,
     369COUNT(DISTINCT r.review_id)   AS review_count,
     370ROUND(AVG(rs.score_value), 2) AS avg_rating
     371FROM Review_Score rs
     372JOIN Review r
     373ON r.review_id = rs.review_id
     374JOIN Project p
     375ON p.project_id = r.project_id
     376JOIN Client_Vendor_Contract cvc
     377ON cvc.contract_id = p.contract_id
     378JOIN Vendor v
     379ON v.vendor_id = cvc.vendor_id
     380GROUP BY v.vendor_id, v.agency_name
     381ORDER BY avg_rating DESC NULLS LAST;
     382}}}
     383
     384`COUNT(DISTINCT r.review_id)` го прикажува бројот на рецензии, додека `AVG` ја пресметува просечната вредност од сите оценети димензии.
     385
     386=== Нерешени Dispute Tickets ===
     387
     388За потребите на dispute системот е креиран `vw_unresolved_dispute_tickets`, кој ги прикажува само тикетите што сè уште не се решени:
     389
     390{{{#!sql
     391CREATE OR REPLACE VIEW vw_unresolved_dispute_tickets AS
     392SELECT dt.ticket_id,
     393dt.filed_at,
     394dt.reason,
     395r.review_id,
     396p.project_id,
     397p.project_name,
     398vu.user_id AS filed_by_vendor_user_id,
     399vu_u.first_name || ' ' || vu_u.last_name
     400AS filed_by_vendor_user,
     401mu.user_id AS assigned_management_user_id,
     402mu_u.first_name || ' ' || mu_u.last_name
     403AS assigned_to_management_user,
     404dt.created_at,
     405dt.updated_at
     406FROM Dispute_Ticket dt
     407JOIN Review r
     408ON r.review_id = dt.review_id
     409JOIN Project p
     410ON p.project_id = r.project_id
     411JOIN Vendor_User vu
     412ON vu.user_id = dt.vendor_user_id
     413JOIN "User" vu_u
     414ON vu_u.user_id = vu.user_id
     415LEFT JOIN Management_User mu
     416ON mu.user_id = dt.assigned_management_user_id
     417LEFT JOIN "User" mu_u
     418ON mu_u.user_id = mu.user_id
     419WHERE dt.is_resolved = false
     420ORDER BY dt.filed_at;
     421}}}
     422
     423За management корисникот се користи `LEFT JOIN`, бидејќи нерешен dispute ticket може сè уште да нема доделен management корисник.
     424
     425=== Број на проекти по статус ===
     426
     427За статистички приказ на состојбата на проектите се користат два погледи кои го пресметуваат бројот на проекти по статус.
     428
     429За vendor:
     430
     431{{{#!sql
     432CREATE OR REPLACE VIEW vw_project_count_by_status_per_vendor AS
     433SELECT v.vendor_id,
     434v.agency_name,
     435ps.status_id,
     436ps.status_name,
     437COUNT(p.project_id) AS project_count
     438FROM Project p
     439JOIN Client_Vendor_Contract cvc
     440ON cvc.contract_id = p.contract_id
     441JOIN Vendor v
     442ON v.vendor_id = cvc.vendor_id
     443JOIN Project_Status ps
     444ON ps.status_id = p.status_id
     445GROUP BY v.vendor_id,
     446v.agency_name,
     447ps.status_id,
     448ps.status_name
     449ORDER BY v.agency_name, ps.status_name;
     450}}}
     451
     452За client:
     453
     454{{{#!sql
     455CREATE OR REPLACE VIEW vw_project_count_by_status_per_client AS
     456SELECT c.client_id,
     457c.company_name,
     458ps.status_id,
     459ps.status_name,
     460COUNT(p.project_id) AS project_count
     461FROM Project p
     462JOIN Client_Vendor_Contract cvc
     463ON cvc.contract_id = p.contract_id
     464JOIN Client c
     465ON c.client_id = cvc.client_id
     466JOIN Project_Status ps
     467ON ps.status_id = p.status_id
     468GROUP BY c.client_id,
     469c.company_name,
     470ps.status_id,
     471ps.status_name
     472ORDER BY c.company_name, ps.status_name;
     473}}}
     474
     475Овие погледи овозможуваат брзо добивање на бројот на проекти во статуси како `Draft`, `In Progress`, `Completed` и останатите дефинирани статуси.
     476
     477=== Договори по Vendor и Client ===
     478
     479За приказ на договорите од двете перспективи се користат `vw_contracts_per_vendor` и `vw_contracts_per_client`.
     480
     481{{{#!sql
     482CREATE OR REPLACE VIEW vw_contracts_per_vendor AS
     483SELECT v.vendor_id,
     484v.agency_name,
     485cvc.contract_id,
     486cvc.contract_number,
     487cvc.contract_title,
     488c.client_id,
     489c.company_name AS client_name,
     490cvc.start_date,
     491cvc.end_date,
     492cvc.total_value,
     493cvc.currency_code,
     494cvc.is_active
     495FROM Client_Vendor_Contract cvc
     496JOIN Vendor v
     497ON v.vendor_id = cvc.vendor_id
     498JOIN Client c
     499ON c.client_id = cvc.client_id
     500ORDER BY v.agency_name,
     501cvc.is_active DESC,
     502cvc.start_date DESC;
     503}}}
     504
     505{{{#!sql
     506CREATE OR REPLACE VIEW vw_contracts_per_client AS
     507SELECT c.client_id,
     508c.company_name,
     509cvc.contract_id,
     510cvc.contract_number,
     511cvc.contract_title,
     512v.vendor_id,
     513v.agency_name AS vendor_name,
     514cvc.start_date,
     515cvc.end_date,
     516cvc.total_value,
     517cvc.currency_code,
     518cvc.is_active
     519FROM Client_Vendor_Contract cvc
     520JOIN Client c
     521ON c.client_id = cvc.client_id
     522JOIN Vendor v
     523ON v.vendor_id = cvc.vendor_id
     524ORDER BY c.company_name,
     525cvc.is_active DESC,
     526cvc.start_date DESC;
     527}}}
     528
     529Со сортирање на `is_active DESC`, активните договори се прикажуваат пред историските договори.
     530
     531=== Vendor претплати ===
     532
     533За приказ на активните и историските претплати на агенциите е дефиниран `vw_vendor_subscriptions`:
     534
     535{{{#!sql
     536CREATE OR REPLACE VIEW vw_vendor_subscriptions AS
     537SELECT v.vendor_id,
     538v.agency_name,
     539st.tier_id,
     540st.tier_name,
     541COALESCE(
     542vs.negotiated_price,
     543st.list_price,
     5440
     545) AS effective_price,
     546vs.start_date,
     547vs.end_date,
     548vs.is_active
     549FROM Vendor_Subscription vs
     550JOIN Vendor v
     551ON v.vendor_id = vs.vendor_id
     552JOIN Subscription_Tier st
     553ON st.tier_id = vs.tier_id
     554ORDER BY v.agency_name,
     555vs.is_active DESC,
     556vs.start_date DESC;
     557}}}
     558
     559Полето `effective_price` ја користи договорената цена доколку постои. Во спротивно се користи стандардната цена од `Subscription_Tier`.
     560
     561На овој начин views обезбедуваат готови прикази за најчестите оперативни и аналитички потреби на системот, без истите `JOIN`, `GROUP BY` и агрегатни операции да се повторуваат во секој прашалник.
     562
    250563== Полнење со податоци ==
    251564