Changes between Version 1 and Version 2 of RelationalModel


Ignore:
Timestamp:
04/19/26 11:49:34 (13 days ago)
Author:
226032
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • RelationalModel

    v1 v2  
    22
    33== Релационен дијаграм ==
     4
     5[[Image(RelationalModel-SmenoPlaner.svg)]]
     6
     7''Прикачени датотеки: `RelationalModel-SmenoPlaner.svg`, `Revised_27032026.vpp(Фајлот ми е 800кб)`''
     8
     9== Документација и дополнителен опис ==
     10
     11=== Multi-tenant изолација по organization ===
     12
     13Секој ентитет кој припаѓа на одредена организација (location, shift_presets, position, users, shift) содржи `organization_id` странски клуч кон табелата `organization`. Ова е свесна архитектурна одлука: наместо посебна база по тенант, сите организации споделуваат иста шема, а изолацијата се спроведува на апликациско ниво преку `organization_id`. Слагот (`slug`) на организацијата е уникатен и служи за URL-friendly идентификација.
     14
     15=== UUID примарни клучеви (varchar 36) ===
     16
     17Сите примарни клучеви се UUID вредности чувани како `varchar(36)`, наместо auto-increment integer. Причина: UUID-а дозволуваат генерација на ID на страната на апликацијата (без round-trip до базата), погодни се за дистрибуирани системи и спречуваат откривање на бројот на записи преку секвенцијални ID-а.
     18
     19=== position е scoped по организација ===
     20
     21Табелата `position` содржи `organization_id` и уникатен индекс на `(organization_id, name)`. Ова значи дека две различни организации можат да имаат позиција со исто име, но во рамки на иста организација имињата мора да бидат уникатни. Позициите се поврзани со корисници преку `user_position` (junction табела) и со шаблони преку `shift_preset_position_requirement`.
     22
     23=== shift_preset_position_requirement — барања по позиција ===
     24
     25Секој шаблон за смена (`shift_presets`) може да дефинира колку вработени од одредена позиција се потребни (`required_count`). CHECK ограничувањето `required_count > 0` гарантира дека вредноста е секогаш позитивна. Уникатниот индекс на `(shift_preset_id, position_id)` спречува дупли барања за иста комбинација.
     26
     27=== swap_request_users — junction табела за замена ===
     28
     29Наместо колони `requested_by` и `taken_by` директно во `swap_request`, тие се изолирани во посебна табела `swap_request_users`. Причина: `taken_by` е nullable (вработен сè уште не ја прифатил замената), а оваа структура јасно ги разделува двете страни на процесот — кој побарал и кој прифатил. Примарен клуч е `swap_request_id` (1:1 врска), со три странски клучеви: кон `swap_request`, и двапати кон `users`.
     30
     31=== CHECK ограничувања на статус полиња ===
     32
     33`leave_request.status` и `swap_request.status` се ограничени на вредностите `('pending', 'approved', 'rejected')` преку CHECK ограничувања. Ова го спречува внесот на невалидни статуси директно на ниво на базата, независно од апликациската логика.