Changes between Version 20 and Version 21 of Normalization


Ignore:
Timestamp:
08/06/26 12:36:16 (34 hours ago)
Author:
231175
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Normalization

    v20 v21  
    66
    77{{{
    8 Universal_Relation_Shifter(
    9 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points, user_course_favorite_ids,
     8Universal_Relation_Shifter( account_id, account_email, account_password_hash, account_name,
     9user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, user_favorite_course_ids,
    1010meeting_reminder_id, meeting_at, meeting_scheduled_at, meeting_sent, meeting_link,
    11 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
     11expert_id,
     12language_id, language_value,
    1213course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    13 course_version_id, version_number, version_creation_date, version_active,
     14course_version_id, version_number, version_created_at, version_is_active,
    1415enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    1516payment_id, payment_amount, payment_date, payment_method, payment_status,
    1617review_id, review_rating, review_comment, review_date,
    17 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
     18course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
    1819course_what_will_be_learned,
    1920course_content_id, content_position,
    20 course_content_translate_id, content_translate_title, content_translate_language,
    21 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    22 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    23 user_course_progress_id, progress_completed, progress_completed_at,
    24 verification_token_uuid, token_created_at, token_expired_at,
     21course_content_translate_id, content_translate_title,
     22course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     23course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     24user_course_progress_id, progress_is_completed, progress_completed_at,
     25verification_token_uuid, token_created_at, token_expires_at,
    2526tag_id, tag_type,
    26 tag_translate_id, tag_translate_language, tag_value
    27 )
    28 }}}
     27tag_translate_id, tag_value )
     28}}}
     29
     30'''Забелешка за јазикот:''' Во претходната верзија секоја релација за превод носеше сопствен атрибут за јазик (course_translate_language, content_translate_language, lecture_language, tag_translate_language). Во новиот модел јазикот е самостоен ентитет (Language), па сите четири релации за превод упатуваат кон истиот атрибут language_id. Во универзалната релација тоа значи дека една торка ги содржи преводите на еден ист јазик.
     31
     32'''Забелешка за сметките:''' Атрибутите за најава (email, password_hash, name) се издвоени во ентитетот Account. Затоа Expert повеќе не носи сопствени атрибути за име и мејл, туку само упатување кон Account.
    2933
    3034----
     
    3539
    3640'''F = {'''
    37  * '''FD1:''' user_id → user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points
    38  * '''FD2:''' verification_token_uuid → token_created_at, token_expired_at, user_id
     41 * '''FD1:''' user_id → user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, account_id
     42 * '''FD2:''' verification_token_uuid → token_created_at, token_expires_at, user_id
    3943 * '''FD3:''' meeting_reminder_id → meeting_at, meeting_scheduled_at, meeting_sent, meeting_link, user_id
    40  * '''FD4:''' expert_id → expert_name, expert_email, expert_login_provider, expert_password_hash
     44 * '''FD4:''' expert_id → account_id
    4145 * '''FD5:''' course_id → course_image_url, course_color, course_difficulty, course_duration_minutes, course_price
    4246 * '''FD6:''' enrollment_id → enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id, payment_id, review_id
     
    4448 * '''FD8:''' review_id → review_rating, review_comment, review_date, enrollment_id
    4549 * '''FD9:''' tag_id → tag_type
    46  * '''FD10:''' tag_translate_id → tag_translate_language, tag_value, tag_id
    47  * '''FD11:''' course_version_id → version_number, version_creation_date, version_active, course_id
    48  * '''FD12:''' course_translate_id → course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id
     50 * '''FD10:''' tag_translate_id → tag_value, tag_id, language_id
     51 * '''FD11:''' course_version_id → version_number, version_created_at, version_is_active, course_id
     52 * '''FD12:''' course_translate_id → course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id
    4953 * '''FD13:''' course_content_id → content_position, course_version_id
    50  * '''FD14:''' course_content_translate_id → content_translate_title, content_translate_language, course_content_id
     54 * '''FD14:''' course_content_translate_id → content_translate_title, course_content_id, language_id
    5155 * '''FD15:''' course_lecture_id → lecture_duration_minutes, lecture_position, lecture_content_type, course_content_id
    52  * '''FD16:''' course_lecture_translate_id → lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id
    53  * '''FD17:''' user_course_progress_id → progress_completed, progress_completed_at, enrollment_id, course_lecture_id
     56 * '''FD16:''' course_lecture_translate_id → lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id
     57 * '''FD17:''' user_course_progress_id → progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id
    5458 * '''FD18:''' user_email → user_id
    55  * '''FD19:''' expert_email → expert_id
     59 * '''FD19:''' account_id → account_email, account_password_hash, account_name
    5660 * '''FD20:''' (course_id, version_number) → course_version_id
    57  * '''FD21:''' (course_id, course_translate_language) → course_translate_id
    58  * '''FD22:''' (course_lecture_id, lecture_language) → course_lecture_translate_id
    59  * '''FD23:''' (course_content_id, content_translate_language) → course_content_translate_id
    60  * '''FD24:''' (tag_id, tag_translate_language) → tag_translate_id
     61 * '''FD21:''' (course_id, language_id) → course_translate_id
     62 * '''FD22:''' (course_lecture_id, language_id) → course_lecture_translate_id
     63 * '''FD23:''' (course_content_id, language_id) → course_content_translate_id
     64 * '''FD24:''' (tag_id, language_id) → tag_translate_id
    6165 * '''FD25:''' (enrollment_id, course_lecture_id) → user_course_progress_id
    6266 * '''FD26:''' (course_version_id, content_position) → course_content_id
    6367 * '''FD27:''' (course_content_id, lecture_position) → course_lecture_id
    6468 * '''FD28:''' (course_translate_id, course_what_will_be_learned) → ∅
    65  * '''FD29:''' (user_id, user_course_favorite_ids) → ∅
     69 * '''FD29:''' (user_id, user_favorite_course_ids) → ∅
     70 * '''FD30:''' account_email → account_id
     71 * '''FD31:''' language_id → language_value
     72 * '''FD32:''' language_value → language_id
     73 * '''FD33:''' meeting_link → meeting_reminder_id
    6674'''}'''
    6775
     76'''Забелешка:''' FD6 го содржи payment_id на десната страна бидејќи ограничувањето `uq_payment_enrollment` дозволува најмногу една наплата по запишување. FD33 произлегува од ограничувањето `uq_meeting_email_reminder_link`. FD30 произлегува од `uq_account_email`, а FD32 од `uq_language_value`.
     77
    6878----
    6979
     
    7787
    7888||= Атрибут =||= Лева страна =||= Десна страна =||= Класификација =||
    79 || user_id || ✓ (FD1) || ✓ (FD2, FD3, FD6, FD18) || и лево и десно ||
     89|| account_id || ✓ (FD19) || ✓ (FD1, FD4, FD30) || и лево и десно ||
     90|| account_email || ✓ (FD30) || ✓ (FD19) || и лево и десно ||
     91|| account_password_hash || ✗ || ✓ (FD19) || десно ||
     92|| account_name || ✗ || ✓ (FD19) || десно ||
     93|| user_id || ✓ (FD1, FD29) || ✓ (FD2, FD3, FD6, FD18) || и лево и десно ||
    8094|| user_name || ✗ || ✓ (FD1) || десно ||
    8195|| user_email || ✓ (FD18) || ✓ (FD1) || и лево и десно ||
    8296|| user_login_provider || ✗ || ✓ (FD1) || десно ||
    8397|| user_password_hash || ✗ || ✓ (FD1) || десно ||
    84 || user_verified || ✗ || ✓ (FD1) || десно ||
    85 || user_profile_complete || ✗ || ✓ (FD1) || десно ||
    86 || user_used_free_consultation || ✗ || ✓ (FD1) || десно ||
     98|| user_is_verified || ✗ || ✓ (FD1) || десно ||
     99|| user_is_profile_complete || ✗ || ✓ (FD1) || десно ||
     100|| user_has_used_free_consultation || ✗ || ✓ (FD1) || десно ||
    87101|| user_company_size || ✗ || ✓ (FD1) || десно ||
    88102|| user_work_position || ✗ || ✓ (FD1) || десно ||
    89103|| user_points || ✗ || ✓ (FD1) || десно ||
    90 || user_course_favorite_ids || ✓ (FD29) || ✗ || лево ||
     104|| user_favorite_course_ids || ✓ (FD29) || ✗ || лево ||
    91105|| verification_token_uuid || ✓ (FD2) || ✗ || лево ||
    92106|| token_created_at || ✗ || ✓ (FD2) || десно ||
    93 || token_expired_at || ✗ || ✓ (FD2) || десно ||
    94 || meeting_reminder_id || ✓ (FD3) || ✗ || лево ||
     107|| token_expires_at || ✗ || ✓ (FD2) || десно ||
     108|| meeting_reminder_id || ✓ (FD3) || ✓ (FD33) || и лево и десно ||
    95109|| meeting_at || ✗ || ✓ (FD3) || десно ||
    96110|| meeting_scheduled_at || ✗ || ✓ (FD3) || десно ||
    97111|| meeting_sent || ✗ || ✓ (FD3) || десно ||
    98 || meeting_link || ✗ || ✓ (FD3) || десно ||
    99 || expert_id || ✓ (FD4) || ✓ (FD19) || и лево и десно ||
    100 || expert_name || ✗ || ✓ (FD4) || десно ||
    101 || expert_email || ✓ (FD19) || ✓ (FD4) || и лево и десно ||
    102 || expert_login_provider || ✗ || ✓ (FD4) || десно ||
    103 || expert_password_hash || ✗ || ✓ (FD4) || десно ||
     112|| meeting_link || ✓ (FD33) || ✓ (FD3) || и лево и десно ||
     113|| expert_id || ✓ (FD4) || ✗ || лево ||
     114|| language_id || ✓ (FD21, FD22, FD23, FD24, FD31) || ✓ (FD10, FD12, FD14, FD16, FD32) || и лево и десно ||
     115|| language_value || ✓ (FD32) || ✓ (FD31) || и лево и десно ||
    104116|| course_id || ✓ (FD5, FD20, FD21) || ✓ (FD11, FD12) || и лево и десно ||
    105117|| course_image_url || ✗ || ✓ (FD5) || десно ||
     
    125137|| tag_type || ✗ || ✓ (FD9) || десно ||
    126138|| tag_translate_id || ✓ (FD10) || ✓ (FD24) || и лево и десно ||
    127 || tag_translate_language || ✓ (FD24) || ✓ (FD10) || и лево и десно ||
    128139|| tag_value || ✗ || ✓ (FD10) || десно ||
    129140|| course_version_id || ✓ (FD11, FD26) || ✓ (FD6, FD13, FD20) || и лево и десно ||
    130141|| version_number || ✓ (FD20) || ✓ (FD11) || и лево и десно ||
    131 || version_creation_date || ✗ || ✓ (FD11) || десно ||
    132 || version_active || ✗ || ✓ (FD11) || десно ||
     142|| version_created_at || ✗ || ✓ (FD11) || десно ||
     143|| version_is_active || ✗ || ✓ (FD11) || десно ||
    133144|| course_translate_id || ✓ (FD12) || ✓ (FD21) || и лево и десно ||
    134 || course_translate_language || ✓ (FD21) || ✓ (FD12) || и лево и десно ||
    135145|| course_title_short || ✗ || ✓ (FD12) || десно ||
    136146|| course_title || ✗ || ✓ (FD12) || десно ||
     
    143153|| course_content_translate_id || ✓ (FD14) || ✓ (FD23) || и лево и десно ||
    144154|| content_translate_title || ✗ || ✓ (FD14) || десно ||
    145 || content_translate_language || ✓ (FD23) || ✓ (FD14) || и лево и десно ||
    146155|| course_lecture_id || ✓ (FD15, FD22, FD25) || ✓ (FD16, FD17, FD27) || и лево и десно ||
    147156|| lecture_duration_minutes || ✗ || ✓ (FD15) || десно ||
     
    150159|| course_lecture_translate_id || ✓ (FD16) || ✓ (FD22) || и лево и десно ||
    151160|| lecture_title || ✗ || ✓ (FD16) || десно ||
    152 || lecture_language || ✓ (FD22) || ✓ (FD16) || и лево и десно ||
    153161|| lecture_content_file_name || ✗ || ✓ (FD16) || десно ||
    154162|| lecture_description || ✗ || ✓ (FD16) || десно ||
    155163|| lecture_content_text || ✗ || ✓ (FD16) || десно ||
    156164|| user_course_progress_id || ✓ (FD17) || ✓ (FD25) || и лево и десно ||
    157 || progress_completed || ✗ || ✓ (FD17) || десно ||
     165|| progress_is_completed || ✗ || ✓ (FD17) || десно ||
    158166|| progress_completed_at || ✗ || ✓ (FD17) || десно ||
    159167
    160 
    161 
    162168=== 3.3 Атрибути кои се појавуваат САМО на лева страна ===
    163169
    164170 * '''verification_token_uuid''' - мора да биде дел од секој кандидат клуч
    165  * '''meeting_reminder_id''' - мора да биде дел од секој кандидат клуч
     171 * '''expert_id''' - мора да биде дел од секој кандидат клуч
    166172 * '''course_what_will_be_learned''' - мора да биде дел од секој кандидат клуч
    167  * '''user_course_favorite_ids''' - мора да биде дел од секој кандидат клуч
     173 * '''user_favorite_course_ids''' - мора да биде дел од секој кандидат клуч
     174
     175'''Меѓусебно зависни парови:''' Атрибутите meeting_reminder_id и meeting_link меѓусебно се определуваат (FD3 и FD33), а ниту еден друг атрибут не ги определува. Затоа точно еден од нив мора да биде дел од секој кандидат клуч; го избираме meeting_reminder_id. Истото важи и за парот account_id и account_email, но тие се достапни преку FD1 од user_id, па не мора да бидат во клучот.
    168176
    169177=== 3.4 Пресметка на затворач ===
    170178
    171 '''Чекор 1:''' Започнуваме со {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids} и пресметуваме затворач:
    172 
    173 {{{
    174 {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids}⁺:
    175 - Од FD2 (verification_token_uuid →): добиваме token_created_at, token_expired_at, user_id
     179'''Чекор 1:''' Започнуваме со {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids} и пресметуваме затворач:
     180
     181{{{
     182{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids}⁺:
     183- Од FD2 (verification_token_uuid →): добиваме token_created_at, token_expires_at, user_id
    176184- Од FD3 (meeting_reminder_id →): добиваме meeting_at, meeting_scheduled_at, meeting_sent, meeting_link, user_id
    177 - Од FD1 (user_id →): добиваме user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points
     185- Од FD1 (user_id →): добиваме user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, account_id
     186- Од FD4 (expert_id →): добиваме account_id
     187- Од FD19 (account_id →): добиваме account_email, account_password_hash, account_name
    178188- Од FD18 (user_email →): добиваме user_id
    179 }}}
    180 
    181 '''{verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids}⁺ ≠ Universal_Relation_Shifter'''
     189- Од FD30 (account_email →): добиваме account_id
     190}}}
     191
     192'''{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids}⁺ ≠ Universal_Relation_Shifter'''
    182193
    183194'''Недостасуваат:'''
    184 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
     195language_id, language_value,
    185196course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    186 course_version_id, version_number, version_creation_date, version_active,
     197course_version_id, version_number, version_created_at, version_is_active,
    187198enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    188199payment_id, payment_amount, payment_date, payment_method, payment_status,
    189200review_id, review_rating, review_comment, review_date,
    190 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    191 course_content_id, content_position,
    192 course_content_translate_id, content_translate_title, content_translate_language,
    193 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    194 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    195 user_course_progress_id, progress_completed, progress_completed_at,
     201course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     202course_content_id, content_position,
     203course_content_translate_id, content_translate_title,
     204course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     205course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     206user_course_progress_id, progress_is_completed, progress_completed_at,
    196207tag_id, tag_type,
    197 tag_translate_id, tag_translate_language, tag_value
     208tag_translate_id, tag_value
    198209
    199210'''Чекор 2:''' Додаваме user_course_progress_id:
    200211
    201212{{{
    202 {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id}⁺:
     213{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id}⁺:
    203214- Сè од претходно, плус:
    204 - Од FD6 (user_course_progress_id →): добиваме progress_completed, progress_completed_at, enrollment_id, course_lecture_id
     215- Од FD17 (user_course_progress_id →): добиваме progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id
    205216- Од FD15 (course_lecture_id →): добиваме lecture_duration_minutes, lecture_position, lecture_content_type, course_content_id
    206217- Од FD13 (course_content_id →): добиваме content_position, course_version_id
     
    208219- Од FD7 (payment_id →): добиваме payment_amount, payment_date, payment_method, payment_status, enrollment_id
    209220- Од FD8 (review_id →): добиваме review_rating, review_comment, review_date, enrollment_id
    210 - Од FD11 (course_version_id →): добиваме version_number, version_creation_date, version_active, course_id
     221- Од FD11 (course_version_id →): добиваме version_number, version_created_at, version_is_active, course_id
    211222- Од FD5 (course_id →): добиваме course_image_url, course_color, course_difficulty, course_duration_minutes, course_price
    212223}}}
    213224
    214 '''{verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id}⁺ ≠ Universal_Relation_Shifter'''
     225'''{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id}⁺ ≠ Universal_Relation_Shifter'''
    215226
    216227'''Недостасуваат:'''
    217 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
    218 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    219 course_content_translate_id, content_translate_title, content_translate_language,
    220 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
     228language_id, language_value,
     229course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     230course_content_translate_id, content_translate_title,
     231course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
    221232tag_id, tag_type,
    222 tag_translate_id, tag_translate_language, tag_value
    223 
    224 '''Чекор 3:''' Додаваме expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id:
    225 
    226 {{{
    227 {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}⁺:
     233tag_translate_id, tag_value
     234
     235'''Чекор 3:''' Додаваме course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id:
     236
     237{{{
     238{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}⁺:
    228239- Сè од претходно, плус:
    229 - Од FD4 (expert_id →): добиваме expert_name, expert_email, expert_login_provider, expert_password_hash
    230 - Од FD16 (course_lecture_translate_id →): добиваме lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id
    231 - Од FD14 (course_content_translate_id →): добиваме content_translate_title, content_translate_language, course_content_id
    232 - Од FD12 (course_translate_id →): добиваме course_translate_language, course_title_short, course_title, course_description_short, course_description
    233 - Од FD10 (tag_translate_id →): добиваме tag_translate_language, tag_value, tag_id
     240- Од FD16 (course_lecture_translate_id →): добиваме lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id
     241- Од FD14 (course_content_translate_id →): добиваме content_translate_title, course_content_id, language_id
     242- Од FD12 (course_translate_id →): добиваме course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id
     243- Од FD10 (tag_translate_id →): добиваме tag_value, tag_id, language_id
     244- Од FD31 (language_id →): добиваме language_value
    234245- Од FD9 (tag_id →): добиваме tag_type
    235246- Од FD28 ({course_translate_id, course_what_will_be_learned} →): добиваме ∅
    236247}}}
    237248
    238 '''{verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}⁺ = Universal_Relation_Shifter''' (ги содржи сите атрибути) ✓
     249'''{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}⁺ = Universal_Relation_Shifter''' (ги содржи сите атрибути) ✓
    239250
    240251=== 3.5 Проверка за минималност ===
    241252
    242253||= Подмножество =||= Затворач =||= = Universal_Relation_Shifter? =||
    243 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids}⁺ || Недостасуваат атрибути од user_course_progress || ✗ НЕ ||
    244 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress}⁺ || Недостасуваат атрибути од expert || ✗ НЕ ||
    245 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id}⁺ || Недостасуваат атрибути од course_translate || ✗ НЕ ||
    246 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_translate_id}⁺ || Недостасуваат атрибути од course_lecture_translate || ✗ НЕ ||
    247 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_translate_id, course_lecture_translate_id}⁺ || Недостасуваат атрибути од course_content_translate || ✗ НЕ ||
    248 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_translate_id, course_lecture_translate_id, course_content_translate_id}⁺ || Недостасуваат атрибути од tag_translate || ✗ НЕ ||
    249 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, enrollment_id, course_lecture_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id} || Сите атрибути се присути || ✓ ДА ||
    250 || {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_translate_id, course_lecture_translate_id, course_content_translate_id, tag_translate_id}⁺ || Сите атрибути се присути || ✓ ДА ||
    251 
    252 '''Заклучок:''' {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id} е минимален и е кандидат клуч.
     254|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids}⁺ || Недостасуваат атрибути од user_course_progress || ✗ НЕ ||
     255|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id}⁺ || Недостасуваат атрибути од course_translate || ✗ НЕ ||
     256|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_translate_id}⁺ || Недостасуваат атрибути од course_lecture_translate || ✗ НЕ ||
     257|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_translate_id, course_lecture_translate_id}⁺ || Недостасуваат атрибути од course_content_translate || ✗ НЕ ||
     258|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_translate_id, course_lecture_translate_id, course_content_translate_id}⁺ || Недостасуваат атрибути од tag_translate || ✗ НЕ ||
     259|| {verification_token_uuid, meeting_link, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}⁺ || Сите атрибути се присутни || ✓ ДА ||
     260|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, enrollment_id, course_lecture_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id} || Сите атрибути се присутни || ✓ ДА ||
     261|| {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}⁺ || Сите атрибути се присутни || ✓ ДА ||
     262
     263'''Заклучок:''' {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id} е минимален и е кандидат клуч.
    253264
    254265=== 3.6 Други кандидат клучеви ===
    255266
    256 Дополнителен кандидате клуч кој го разгледував беше '''{verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, enrollment_id, course_lecture_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}''', каде наместо user_course_progress_id присутни се enrollment_id и course_lecture_id. Меѓутоа овој кандидат клуч е поголем од тој со user_course_progress_id, па затоа не го земам во предвид при бирање на примарен клуч.
     267Дополнителен кандидат клуч кој го разгледував беше '''{verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, enrollment_id, course_lecture_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}''', каде наместо user_course_progress_id присутни се enrollment_id и course_lecture_id. Меѓутоа овој кандидат клуч е поголем од тој со user_course_progress_id, па затоа не го земам во предвид при бирање на примарен клуч.
     268
     269Втор кандидат клуч со иста големина се добива ако наместо meeting_reminder_id се земе meeting_link (FD33). Го избирам meeting_reminder_id бидејќи е сурогат клуч со фиксна должина, наспроти meeting_link кој е текстуален атрибут.
    257270
    258271=== 3.7 Избор на примарен клуч ===
    259272
    260 '''Избран примарен клуч: {verification_token_uuid, meeting_reminder_id, course_what_will_be_learned, user_course_favorite_ids, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}'''
     273'''Избран примарен клуч: {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}'''
    261274
    262275'''Образложение:'''
     
    277290
    278291{{{
    279 Course_What_Will_Be_Learned(course_translate_id, course_what_will_be_learned)
     292Course_Translate_What_Will_Be_Learned(course_translate_id, course_what_will_be_learned)
    280293   PK: {course_translate_id, course_what_will_be_learned}
    281294
     
    283296
    284297Universal_Relation_Shifter_Base_1(
    285 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points, user_course_favorite_ids,
     298account_id, account_email, account_password_hash, account_name,
     299user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, user_favorite_course_ids,
    286300meeting_reminder_id, meeting_at, meeting_scheduled_at, meeting_sent, meeting_link,
    287 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
     301expert_id,
     302language_id, language_value,
    288303course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    289 course_version_id, version_number, version_creation_date, version_active,
     304course_version_id, version_number, version_created_at, version_is_active,
    290305enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    291306payment_id, payment_amount, payment_date, payment_method, payment_status,
    292307review_id, review_rating, review_comment, review_date,
    293 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    294 course_content_id, content_position,
    295 course_content_translate_id, content_translate_title, content_translate_language,
    296 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    297 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    298 user_course_progress_id, progress_completed, progress_completed_at,
    299 verification_token_uuid, token_created_at, token_expired_at,
     308course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     309course_content_id, content_position,
     310course_content_translate_id, content_translate_title,
     311course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     312course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     313user_course_progress_id, progress_is_completed, progress_completed_at,
     314verification_token_uuid, token_created_at, token_expires_at,
    300315tag_id, tag_type,
    301 tag_translate_id, tag_translate_language, tag_value
    302 )
    303    PK: {verification_token_uuid, meeting_reminder_id, user_course_favorite_ids, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
     316tag_translate_id, tag_value
     317)
     318   PK: {verification_token_uuid, meeting_reminder_id, expert_id, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
    304319}}}
    305320
    306321'''Проверка за lossless join:''' Може да се реконструира преку course_translate_id
    307322
    308 '''Проверка за dependency preservation:''' FD28 е зачувана во Course_What_Will_Be_Learned
     323'''Проверка за dependency preservation:''' FD28 е зачувана во Course_Translate_What_Will_Be_Learned
    309324
    310325=== Чекор 4.2: Декомпозиција на релацијата Universal_Relation_Shifter ===
    311326
    312 '''Нарушува 1NF: '''Релацијата не е во 1NF бидејќи атрибутот user_course_favorite_ids претставува повеќевредносен (multi-valued) атрибут. Секој user може да има повеќе ставки од user_course_favorite_ids.
     327'''Нарушува 1NF: '''Релацијата не е во 1NF бидејќи атрибутот user_favorite_course_ids претставува повеќевредносен (multi-valued) атрибут. Секој user може да има повеќе ставки од user_favorite_course_ids.
    313328
    314329'''Декомпозиција:'''
    315330
    316331{{{
    317 User_Course_Favorite_Id(user_id, user_course_favorite_id)
    318    PK: {user_id, user_course_favorite_id}
    319 
    320 Universal_Relation_Shifter_Base = Universal_Relation_Shifter_Base_1 - {user_course_favorite_ids}
     332User_Favorite_Course(user_id, course_id)
     333   PK: {user_id, course_id}
     334
     335Universal_Relation_Shifter_Base = Universal_Relation_Shifter_Base_1 - {user_favorite_course_ids}
    321336
    322337Universal_Relation_Shifter_Base(
    323 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
     338account_id, account_email, account_password_hash, account_name,
     339user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
    324340meeting_reminder_id, meeting_at, meeting_scheduled_at, meeting_sent, meeting_link,
    325 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
     341expert_id,
     342language_id, language_value,
    326343course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    327 course_version_id, version_number, version_creation_date, version_active,
     344course_version_id, version_number, version_created_at, version_is_active,
    328345enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    329346payment_id, payment_amount, payment_date, payment_method, payment_status,
    330347review_id, review_rating, review_comment, review_date,
    331 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    332 course_content_id, content_position,
    333 course_content_translate_id, content_translate_title, content_translate_language,
    334 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    335 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    336 user_course_progress_id, progress_completed, progress_completed_at,
    337 verification_token_uuid, token_created_at, token_expired_at,
     348course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     349course_content_id, content_position,
     350course_content_translate_id, content_translate_title,
     351course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     352course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     353user_course_progress_id, progress_is_completed, progress_completed_at,
     354verification_token_uuid, token_created_at, token_expires_at,
    338355tag_id, tag_type,
    339 tag_translate_id, tag_translate_language, tag_value
    340 )
    341    PK: {verification_token_uuid, meeting_reminder_id, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
     356tag_translate_id, tag_value
     357)
     358   PK: {verification_token_uuid, meeting_reminder_id, expert_id, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
    342359}}}
    343360
    344361'''Проверка за lossless join:''' Може да се реконструира преку user_id
    345362
    346 '''Проверка за dependency preservation:''' FD29 е зачувана во User_Course_Favorite_Id
     363'''Проверка за dependency preservation:''' FD29 е зачувана во User_Favorite_Course
    347364
    348365
     
    351368За да биде во 2NF, секој не-клучен атрибут мора целосно да зависи од примарниот клуч (нема парцијални зависности).
    352369
    353 Примарен клуч во Universal_Relation_Shifter_Base: '''{verification_token_uuid, meeting_reminder_id, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}'''
     370Примарен клуч во Universal_Relation_Shifter_Base: '''{verification_token_uuid, meeting_reminder_id, expert_id, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}'''
    354371
    355372'''Парцијални зависности (атрибути кои зависат од дел од клучот):'''
    356373||= FD =||= Детерминант =||= Дел од клуч? =||= Парцијална зависност? =||
    357 || FD1: user_id → user_* || user_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
    358 || FD2: verification_token_uuid → token_created_at, token_expired_at, user_id || verification_token_uuid || ДА (дел од примарен клуч) || '''ДА''' ||
     374|| FD1: user_id → user_*, account_id || user_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
     375|| FD2: verification_token_uuid → token_created_at, token_expires_at, user_id || verification_token_uuid || ДА (дел од примарен клуч) || '''ДА''' ||
    359376|| FD3: meeting_reminder_id → meeting_at, meeting_scheduled_at, meeting_sent, meeting_link, user_id || meeting_reminder_id || ДА (дел од примарен клуч) || '''ДА''' ||
    360 || FD4: expert_id → expert_name, expert_email, expert_login_provider, expert_password_hash || expert_id || ДА (дел од примарен клуч) || '''ДА''' ||
     377|| FD4: expert_id → account_id || expert_id || ДА (дел од примарен клуч) || '''ДА''' ||
    361378|| FD5: course_id → course_image_url, course_color, course_difficulty, course_duration_minutes, course_price || course_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
    362379|| FD6: enrollment_id → enrollment_*, user_id, course_version_id, payment_id, review_id || enrollment_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
     
    364381|| FD8: review_id → review_rating, review_comment, review_date, enrollment_id || review_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
    365382|| FD9: tag_id → tag_type || tag_id || НЕ (транзитивно преку tag_translate_id) || Не директно ||
    366 || FD10: tag_translate_id → tag_translate_language, tag_value, tag_id || tag_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
    367 || FD11: course_version_id → version_number, version_creation_date, version_active, course_id || course_version_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
    368 || FD12: course_translate_id → course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id || course_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
     383|| FD10: tag_translate_id → tag_value, tag_id, language_id || tag_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
     384|| FD11: course_version_id → version_number, version_created_at, version_is_active, course_id || course_version_id || НЕ (транзитивно преку user_course_progress_id) || Не директно ||
     385|| FD12: course_translate_id → course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id || course_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
    369386|| FD13: course_content_id → content_position, course_version_id || course_content_id || НЕ (транзитивно преку course_content_translate_id) || Не директно ||
    370 || FD14: course_content_translate_id → content_translate_title, content_translate_language, course_content_id || course_content_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
     387|| FD14: course_content_translate_id → content_translate_title, course_content_id, language_id || course_content_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
    371388|| FD15: course_lecture_id → lecture_duration_minutes, lecture_position, lecture_content_type, course_content_id || course_lecture_id || НЕ (транзитивно преку course_lecture_translate_id) || Не директно ||
    372 || FD16: course_lecture_translate_id → lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id || course_lecture_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
    373 || FD17: user_course_progress_id → progress_completed, progress_completed_at, enrollment_id, course_lecture_id || user_course_progress_id || ДА (дел од примарен клуч) || '''ДА''' ||
     389|| FD16: course_lecture_translate_id → lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id || course_lecture_translate_id || ДА (дел од примарен клуч) || '''ДА''' ||
     390|| FD17: user_course_progress_id → progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id || user_course_progress_id || ДА (дел од примарен клуч) || '''ДА''' ||
    374391|| FD18: user_email → user_id || user_email || НЕ || Не ||
    375 || FD19: expert_email → expert_id || expert_email || НЕ || Не ||
     392|| FD19: account_id → account_email, account_password_hash, account_name || account_id || НЕ (транзитивно преку expert_id и user_id) || Не директно ||
    376393|| FD20: (course_id, version_number) → course_version_id || course_id, version_number || НЕ || Не ||
    377 || FD21: (course_id, course_translate_language) → course_translate_id || course_id, course_translate_language || НЕ || Не ||
    378 || FD22: (course_lecture_id, lecture_language) → course_lecture_translate_id || course_lecture_id, lecture_language || НЕ || Не ||
    379 || FD23: (course_content_id, content_translate_language) → course_content_translate_id || course_content_id, content_translate_language || НЕ || Не ||
    380 || FD24: (tag_id, tag_translate_language) → tag_translate_id || tag_id, tag_translate_language || НЕ || Не ||
     394|| FD21: (course_id, language_id) → course_translate_id || course_id, language_id || НЕ || Не ||
     395|| FD22: (course_lecture_id, language_id) → course_lecture_translate_id || course_lecture_id, language_id || НЕ || Не ||
     396|| FD23: (course_content_id, language_id) → course_content_translate_id || course_content_id, language_id || НЕ || Не ||
     397|| FD24: (tag_id, language_id) → tag_translate_id || tag_id, language_id || НЕ || Не ||
    381398|| FD25: (enrollment_id, course_lecture_id) → user_course_progress_id || enrollment_id, course_lecture_id || НЕ || Не ||
    382399|| FD26: (course_version_id, content_position) → course_content_id || course_version_id, content_position || НЕ || Не ||
    383400|| FD27: (course_content_id, lecture_position) → course_lecture_id || course_content_id, lecture_position || НЕ || Не ||
     401|| FD30: account_email → account_id || account_email || НЕ || Не ||
     402|| FD31: language_id → language_value || language_id || НЕ (транзитивно преку course_translate_id) || Не директно ||
     403|| FD32: language_value → language_id || language_value || НЕ || Не ||
     404|| FD33: meeting_link → meeting_reminder_id || meeting_link || НЕ || Не ||
    384405
    385406'''Заклучок:''' Релацијата не е во 2NF бидејќи има парцијални зависности. Атрибутите на '''FD2, FD3, FD4, FD10, FD12, FD14, FD16, FD17''' зависат само од дел од примарниот клуч, а не од целиот клуч.
     
    387408'''Идентификувани парцијални зависности што ја нарушуваат 2NF:'''
    388409
    389  1. '''FD2:''' verification_token_uuid → token_created_at, token_expired_at, user_id
     410 1. '''FD2:''' verification_token_uuid → token_created_at, token_expires_at, user_id
    390411 2. '''FD3:''' meeting_reminder_id → meeting_at, meeting_scheduled_at, meeting_sent, meeting_link, user_id
    391  3. '''FD4:''' expert_id → expert_name, expert_email, expert_login_provider, expert_password_hash
    392  4. '''FD10:''' tag_translate_id → tag_translate_language, tag_value, tag_id
    393  5. '''FD12:''' course_translate_id → course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id
    394  6. '''FD14:''' course_content_translate_id → content_translate_title, content_translate_language, course_content_id
    395  7. '''FD16:''' course_lecture_translate_id → lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id
    396  8. '''FD17:''' user_course_progress_id → progress_completed, progress_completed_at, enrollment_id, course_lecture_id
     412 3. '''FD4:''' expert_id → account_id
     413 4. '''FD10:''' tag_translate_id → tag_value, tag_id, language_id
     414 5. '''FD12:''' course_translate_id → course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id
     415 6. '''FD14:''' course_content_translate_id → content_translate_title, course_content_id, language_id
     416 7. '''FD16:''' course_lecture_translate_id → lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id
     417 8. '''FD17:''' user_course_progress_id → progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id
    397418
    398419
     
    401422== 5. 2NF Декомпозиција ==
    402423
     424'''Забелешка за надворешните клучеви:''' При секоја декомпозиција, атрибутот кој служи како надворешен клуч (account_id, language_id, course_id, course_content_id, ...) се пренесува во новата релација, но останува и во базната релација сè додека не се извлече неговиот сопствен ентитет.
     425
    403426=== Чекор 5.1: Декомпозиција по FD2 (verification_token_uuid → ...) ===
    404427
    405 '''Нарушува 2NF:''' verification_token_uuid е дел од примарниот клуч, а token_created_at, token_expired_at зависат само од verification_token_uuid.
     428'''Нарушува 2NF:''' verification_token_uuid е дел од примарниот клуч, а token_created_at, token_expires_at зависат само од verification_token_uuid.
    406429
    407430'''Декомпозиција:'''
    408431
    409432{{{
    410 Verification_Token(verification_token_uuid, token_created_at, token_expired_at, user_id)
     433Verification_Token(verification_token_uuid, token_created_at, token_expires_at, user_id)
    411434   PK: verification_token_uuid
    412435
    413 Universal_Relation_Shifter_Base_1 = Universal_Relation_Shifter_Base - {verification_token_uuid, token_created_at, token_expired_at}
     436Universal_Relation_Shifter_Base_1 = Universal_Relation_Shifter_Base - {verification_token_uuid, token_created_at, token_expires_at}
    414437
    415438Universal_Relation_Shifter_Base_1(
    416 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
     439account_id, account_email, account_password_hash, account_name,
     440user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
    417441meeting_reminder_id, meeting_at, meeting_scheduled_at, meeting_sent, meeting_link,
    418 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
     442expert_id,
     443language_id, language_value,
    419444course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    420 course_version_id, version_number, version_creation_date, version_active,
     445course_version_id, version_number, version_created_at, version_is_active,
    421446enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    422447payment_id, payment_amount, payment_date, payment_method, payment_status,
    423448review_id, review_rating, review_comment, review_date,
    424 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    425 course_content_id, content_position,
    426 course_content_translate_id, content_translate_title, content_translate_language,
    427 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    428 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    429 user_course_progress_id, progress_completed, progress_completed_at,
     449course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     450course_content_id, content_position,
     451course_content_translate_id, content_translate_title,
     452course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     453course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     454user_course_progress_id, progress_is_completed, progress_completed_at,
    430455tag_id, tag_type,
    431 tag_translate_id, tag_translate_language, tag_value
    432 )
    433    PK: {meeting_reminder_id, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
     456tag_translate_id, tag_value
     457)
     458   PK: {meeting_reminder_id, expert_id, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
    434459}}}
    435460
     
    451476
    452477Universal_Relation_Shifter_Base_2(
    453 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    454 expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash,
     478account_id, account_email, account_password_hash, account_name,
     479user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     480expert_id,
     481language_id, language_value,
    455482course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    456 course_version_id, version_number, version_creation_date, version_active,
     483course_version_id, version_number, version_created_at, version_is_active,
    457484enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    458485payment_id, payment_amount, payment_date, payment_method, payment_status,
    459486review_id, review_rating, review_comment, review_date,
    460 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    461 course_content_id, content_position,
    462 course_content_translate_id, content_translate_title, content_translate_language,
    463 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    464 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    465 user_course_progress_id, progress_completed, progress_completed_at,
     487course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     488course_content_id, content_position,
     489course_content_translate_id, content_translate_title,
     490course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     491course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     492user_course_progress_id, progress_is_completed, progress_completed_at,
    466493tag_id, tag_type,
    467 tag_translate_id, tag_translate_language, tag_value
    468 )
    469    PK: {user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
     494tag_translate_id, tag_value
     495)
     496   PK: {expert_id, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
    470497}}}
    471498
    472499'''Проверка за lossless join:''' Може да се реконструира преку user_id
    473  
    474 '''Проверка за dependency preservation:''' FD3 е зачувана во Meeting_Reminder
     500 
     501'''Проверка за dependency preservation:''' FD3 и FD33 се зачувани во Meeting_Reminder
    475502
    476503=== Чекор 5.3: Декомпозиција по FD4 (expert_id → ...) ===
    477504
    478 '''Нарушува 2NF:''' expert_id е дел од примарниот клуч, а expert_name, expert_email, expert_login_provider, expert_password_hash зависат само од expert_id.
     505'''Нарушува 2NF:''' expert_id е дел од примарниот клуч, а account_id зависи само од expert_id.
    479506
    480507'''Декомпозиција:'''
    481508
    482509{{{
    483 Expert(expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash)
     510Expert(expert_id, account_id)
    484511   PK: expert_id
    485512
    486 Universal_Relation_Shifter_Base_3 = Universal_Relation_Shifter_Base_2 - {expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash}
     513Universal_Relation_Shifter_Base_3 = Universal_Relation_Shifter_Base_2 - {expert_id}
    487514
    488515Universal_Relation_Shifter_Base_3(
    489 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    490 expert_id,
     516account_id, account_email, account_password_hash, account_name,
     517user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     518language_id, language_value,
    491519course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    492 course_version_id, version_number, version_creation_date, version_active,
     520course_version_id, version_number, version_created_at, version_is_active,
    493521enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    494522payment_id, payment_amount, payment_date, payment_method, payment_status,
    495523review_id, review_rating, review_comment, review_date,
    496 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    497 course_content_id, content_position,
    498 course_content_translate_id, content_translate_title, content_translate_language,
    499 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    500 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    501 user_course_progress_id, progress_completed, progress_completed_at,
     524course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     525course_content_id, content_position,
     526course_content_translate_id, content_translate_title,
     527course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     528course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     529user_course_progress_id, progress_is_completed, progress_completed_at,
    502530tag_id, tag_type,
    503 tag_translate_id, tag_translate_language, tag_value
     531tag_translate_id, tag_value
    504532)
    505533   PK: {user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}
    506534}}}
    507535
    508 '''Проверка за lossless join:''' Може да се реконструира преку expert_id
    509  
     536'''Проверка за lossless join:''' Може да се реконструира преку account_id
     537 
    510538'''Проверка за dependency preservation:''' FD4 е зачувана во Expert
    511539
    512540=== Чекор 5.4: Декомпозиција по FD10 (tag_translate_id → ...) ===
    513541
    514 '''Нарушува 2NF:''' tag_translate_id е дел од примарниот клуч, а tag_translate_language, tag_value зависат само од tag_translate_id.
     542'''Нарушува 2NF:''' tag_translate_id е дел од примарниот клуч, а tag_value зависи само од tag_translate_id.
    515543
    516544'''Декомпозиција:'''
    517545
    518546{{{
    519 Tag_Translate(tag_translate_id, tag_translate_language, tag_value, tag_id)
     547Tag_Translate(tag_translate_id, tag_value, tag_id, language_id)
    520548   PK: tag_translate_id
    521549
    522 Universal_Relation_Shifter_Base_4 = Universal_Relation_Shifter_Base_3 - {tag_translate_id, tag_translate_language, tag_value}
     550Universal_Relation_Shifter_Base_4 = Universal_Relation_Shifter_Base_3 - {tag_translate_id, tag_value}
    523551
    524552Universal_Relation_Shifter_Base_4(
    525 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    526 expert_id,
     553account_id, account_email, account_password_hash, account_name,
     554user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     555language_id, language_value,
    527556course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    528 course_version_id, version_number, version_creation_date, version_active,
     557course_version_id, version_number, version_created_at, version_is_active,
    529558enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    530559payment_id, payment_amount, payment_date, payment_method, payment_status,
    531560review_id, review_rating, review_comment, review_date,
    532 course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long,
    533 course_content_id, content_position,
    534 course_content_translate_id, content_translate_title, content_translate_language,
    535 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    536 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    537 user_course_progress_id, progress_completed, progress_completed_at,
     561course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long,
     562course_content_id, content_position,
     563course_content_translate_id, content_translate_title,
     564course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     565course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     566user_course_progress_id, progress_is_completed, progress_completed_at,
    538567tag_id, tag_type
    539568)
     
    542571
    543572'''Проверка за lossless join:''' Може да се реконструира преку tag_id
    544  
     573 
    545574'''Проверка за dependency preservation:''' FD10 е зачувана во Tag_Translate
    546575
    547576=== Чекор 5.5: Декомпозиција по FD12 (course_translate_id → ...) ===
    548577
    549 '''Нарушува 2NF:''' course_translate_id е дел од примарниот клуч, а course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long зависат само од course_translate_id.
     578'''Нарушува 2NF:''' course_translate_id е дел од примарниот клуч, а course_title_short, course_title, course_description_short, course_description, course_description_long зависат само од course_translate_id.
    550579
    551580'''Декомпозиција:'''
    552581
    553582{{{
    554 Course_Translate(course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id)
     583Course_Translate(course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id)
    555584   PK: course_translate_id
    556585
    557 Universal_Relation_Shifter_Base_5 = Universal_Relation_Shifter_Base_4 - {course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long}
     586Universal_Relation_Shifter_Base_5 = Universal_Relation_Shifter_Base_4 - {course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long}
    558587
    559588Universal_Relation_Shifter_Base_5(
    560 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    561 expert_id,
     589account_id, account_email, account_password_hash, account_name,
     590user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     591language_id, language_value,
    562592course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    563 course_version_id, version_number, version_creation_date, version_active,
     593course_version_id, version_number, version_created_at, version_is_active,
    564594enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    565595payment_id, payment_amount, payment_date, payment_method, payment_status,
    566596review_id, review_rating, review_comment, review_date,
    567597course_content_id, content_position,
    568 course_content_translate_id, content_translate_title, content_translate_language,
    569 course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    570 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    571 user_course_progress_id, progress_completed, progress_completed_at,
     598course_content_translate_id, content_translate_title,
     599course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     600course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     601user_course_progress_id, progress_is_completed, progress_completed_at,
    572602tag_id, tag_type
    573603)
     
    576606
    577607'''Проверка за lossless join:''' Може да се реконструира преку course_id
    578  
     608 
    579609'''Проверка за dependency preservation:''' FD12 е зачувана во Course_Translate
    580610
    581611=== Чекор 5.6: Декомпозиција по FD14 (course_content_translate_id → ...) ===
    582612
    583 '''Нарушува 2NF:''' course_content_translate_id е дел од примарниот клуч, а content_translate_title, content_translate_language зависат само од course_content_translate_id.
     613'''Нарушува 2NF:''' course_content_translate_id е дел од примарниот клуч, а content_translate_title зависи само од course_content_translate_id.
    584614
    585615'''Декомпозиција:'''
    586616
    587617{{{
    588 Course_Content_Translate(course_content_translate_id, content_translate_title, content_translate_language, course_content_id)
     618Course_Content_Translate(course_content_translate_id, content_translate_title, course_content_id, language_id)
    589619   PK: course_content_translate_id
    590620
    591 Universal_Relation_Shifter_Base_6 = Universal_Relation_Shifter_Base_5 - {course_content_translate_id, content_translate_title, content_translate_language}
     621Universal_Relation_Shifter_Base_6 = Universal_Relation_Shifter_Base_5 - {course_content_translate_id, content_translate_title}
    592622
    593623Universal_Relation_Shifter_Base_6(
    594 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    595 expert_id,
     624account_id, account_email, account_password_hash, account_name,
     625user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     626language_id, language_value,
    596627course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    597 course_version_id, version_number, version_creation_date, version_active,
     628course_version_id, version_number, version_created_at, version_is_active,
    598629enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    599630payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    601632course_content_id, content_position,
    602633course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    603 course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text,
    604 user_course_progress_id, progress_completed, progress_completed_at,
     634course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text,
     635user_course_progress_id, progress_is_completed, progress_completed_at,
    605636tag_id, tag_type
    606637)
     
    609640
    610641'''Проверка за lossless join:''' Може да се реконструира преку course_content_id
    611  
     642 
    612643'''Проверка за dependency preservation:''' FD14 е зачувана во Course_Content_Translate
    613644
    614645=== Чекор 5.7: Декомпозиција по FD16 (course_lecture_translate_id → ...) ===
    615646
    616 '''Нарушува 2NF:''' course_lecture_translate_id е дел од примарниот клуч, а lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text зависат само од course_lecture_translate_id.
     647'''Нарушува 2NF:''' course_lecture_translate_id е дел од примарниот клуч, а lecture_title, lecture_content_file_name, lecture_description, lecture_content_text зависат само од course_lecture_translate_id.
    617648
    618649'''Декомпозиција:'''
    619650
    620651{{{
    621 Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id)
     652Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id)
    622653   PK: course_lecture_translate_id
    623654
    624 Universal_Relation_Shifter_Base_7 = Universal_Relation_Shifter_Base_6 - {course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text}
     655Universal_Relation_Shifter_Base_7 = Universal_Relation_Shifter_Base_6 - {course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text}
    625656
    626657Universal_Relation_Shifter_Base_7(
    627 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    628 expert_id,
     658account_id, account_email, account_password_hash, account_name,
     659user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     660language_id, language_value,
    629661course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    630 course_version_id, version_number, version_creation_date, version_active,
     662course_version_id, version_number, version_created_at, version_is_active,
    631663enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    632664payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    634666course_content_id, content_position,
    635667course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
    636 user_course_progress_id, progress_completed, progress_completed_at,
     668user_course_progress_id, progress_is_completed, progress_completed_at,
    637669tag_id, tag_type
    638670)
     
    641673
    642674'''Проверка за lossless join:''' Може да се реконструира преку course_lecture_id
    643  
     675 
    644676'''Проверка за dependency preservation:''' FD16 е зачувана во Course_Lecture_Translate
    645677
    646678=== Чекор 5.8: Декомпозиција по FD17 (user_course_progress_id → ...) ===
    647679
    648 '''Нарушува 2NF:''' user_course_progress_id е дел од примарниот клуч, а progress_completed, progress_completed_at зависат само од user_course_progress_id.
     680'''Нарушува 2NF:''' user_course_progress_id е дел од примарниот клуч, а progress_is_completed, progress_completed_at зависат само од user_course_progress_id.
    649681
    650682'''Декомпозиција:'''
    651683
    652684{{{
    653 User_Course_Progress(user_course_progress_id, progress_completed, progress_completed_at, enrollment_id, course_lecture_id)
     685User_Course_Progress(user_course_progress_id, progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id)
    654686   PK: user_course_progress_id
    655687
    656 Universal_Relation_Shifter_Base_8 = Universal_Relation_Shifter_Base_7 - {user_course_progress_id, progress_completed, progress_completed_at}
     688Universal_Relation_Shifter_Base_8 = Universal_Relation_Shifter_Base_7 - {user_course_progress_id, progress_is_completed, progress_completed_at}
    657689
    658690Universal_Relation_Shifter_Base_8(
    659 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    660 expert_id,
     691account_id, account_email, account_password_hash, account_name,
     692user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     693language_id, language_value,
    661694course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    662 course_version_id, version_number, version_creation_date, version_active,
     695course_version_id, version_number, version_created_at, version_is_active,
    663696enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    664697payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    672705
    673706'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id и course_lecture_id
    674  
     707 
    675708'''Проверка за dependency preservation:''' FD17 е зачувана во User_Course_Progress
    676709
     
    678711
    679712{{{
    680 User_Course_Favorite_Id(user_id, user_course_favorite_id)
    681    PK: {user_id, user_course_favorite_id}
    682 
    683 Course_What_Will_Be_Learned(course_translate_id, course_what_will_be_learned)
     713User_Favorite_Course(user_id, course_id)
     714   PK: {user_id, course_id}
     715
     716Course_Translate_What_Will_Be_Learned(course_translate_id, course_what_will_be_learned)
    684717   PK: {course_translate_id, course_what_will_be_learned}
    685718
    686 Verification_Token(verification_token_uuid, token_created_at, token_expired_at, user_id)
     719Verification_Token(verification_token_uuid, token_created_at, token_expires_at, user_id)
    687720   PK: verification_token_uuid
    688721
     
    690723   PK: meeting_reminder_id
    691724
    692 Expert(expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash)
     725Expert(expert_id, account_id)
    693726   PK: expert_id
    694727
    695 Tag_Translate(tag_translate_id, tag_translate_language, tag_value, tag_id)
     728Tag_Translate(tag_translate_id, tag_value, tag_id, language_id)
    696729   PK: tag_translate_id
    697730
    698 Course_Translate(course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id)
     731Course_Translate(course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id)
    699732   PK: course_translate_id
    700733
    701 Course_Content_Translate(course_content_translate_id, content_translate_title, content_translate_language, course_content_id)
     734Course_Content_Translate(course_content_translate_id, content_translate_title, course_content_id, language_id)
    702735   PK: course_content_translate_id
    703736
    704 Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id)
     737Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id)
    705738   PK: course_lecture_translate_id
    706739
    707 User_Course_Progress(user_course_progress_id, progress_completed, progress_completed_at, enrollment_id, course_lecture_id)
     740User_Course_Progress(user_course_progress_id, progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id)
    708741   PK: user_course_progress_id
    709742
    710743Universal_Relation_Shifter_Base_8(
    711 user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points,
    712 expert_id,
     744account_id, account_email, account_password_hash, account_name,
     745user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points,
     746language_id, language_value,
    713747course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    714 course_version_id, version_number, version_creation_date, version_active,
     748course_version_id, version_number, version_created_at, version_is_active,
    715749enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    716750payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    729763=== Проверка за транзитивни зависности во секоја релација ===
    730764
    731 ==== Verification_Token(verification_token_uuid, token_created_at, token_expired_at, user_id) ====
     765==== Verification_Token(verification_token_uuid, token_created_at, token_expires_at, user_id) ====
    732766
    733767'''Транзитивни зависности:'''
     
    740774
    741775'''Транзитивни зависности:'''
    742  * meeting_reminder_id → userId → user_*?
     776 * meeting_reminder_id → user_id → user_*?
    743777   * user_* атрибутите НЕ се во Meeting_Reminder.
     778 * meeting_link → meeting_reminder_id (FD33) е зависност кон клучот, не транзитивна зависност.
    744779
    745780'''Заклучок:''' Meeting_Reminder е во 3NF ✓
    746781
    747 ==== Expert(expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash) ====
     782==== Expert(expert_id, account_id) ====
    748783
    749784'''Транзитивни зависности:'''
    750  * Нема не-клучни атрибути кои одредуваат други не-клучни атрибути.
     785 * expert_id → account_id → account_*?
     786   * account_* атрибутите НЕ се во Expert.
    751787
    752788'''Заклучок:''' Expert е во 3NF ✓
    753789
    754 ==== Tag_Translate(tag_translate_id, tag_translate_language, tag_value, tag_id) ====
     790==== Tag_Translate(tag_translate_id, tag_value, tag_id, language_id) ====
    755791
    756792'''Транзитивни зависности:'''
    757793 * tag_translate_id → tag_id → tag_*?
    758794   * tag_* атрибутите НЕ се во Tag_Translate.
     795 * tag_translate_id → language_id → language_value?
     796   * language_value НЕ е во Tag_Translate.
    759797
    760798'''Заклучок:''' Tag_Translate е во 3NF ✓
    761799
    762 ==== Course_Translate(course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id) ====
     800==== Course_Translate(course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id) ====
    763801
    764802'''Транзитивни зависности:'''
    765803 * course_translate_id → course_id → course_*?
    766804   * course_* атрибутите НЕ се во Course_Translate.
     805 * course_translate_id → language_id → language_value?
     806   * language_value НЕ е во Course_Translate.
    767807
    768808'''Заклучок:''' Course_Translate е во 3NF ✓
    769809
    770 ==== Course_Content_Translate(course_content_translate_id, content_translate_title, content_translate_language, course_content_id) ====
     810==== Course_Content_Translate(course_content_translate_id, content_translate_title, course_content_id, language_id) ====
    771811
    772812'''Транзитивни зависности:'''
    773813 * course_content_translate_id → course_content_id → course_content_*?
    774814   * course_content_* атрибутите НЕ се во Course_Content_Translate.
     815 * course_content_translate_id → language_id → language_value?
     816   * language_value НЕ е во Course_Content_Translate.
    775817
    776818'''Заклучок:''' Course_Content_Translate е во 3NF ✓
    777819
    778 ==== Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id) ====
     820==== Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id) ====
    779821
    780822'''Транзитивни зависности:'''
    781823 * course_lecture_translate_id → course_lecture_id → course_lecture_*?
    782824   * course_lecture_* атрибутите НЕ се во Course_Lecture_Translate.
     825 * course_lecture_translate_id → language_id → language_value?
     826   * language_value НЕ е во Course_Lecture_Translate.
    783827
    784828'''Заклучок:''' Course_Lecture_Translate е во 3NF ✓
    785829
    786 ==== User_Course_Progress(user_course_progress_id, progress_completed, progress_completed_at, enrollment_id, course_lecture_id) ====
     830==== User_Course_Progress(user_course_progress_id, progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id) ====
    787831
    788832'''Транзитивни зависности:'''
     
    799843
    800844'''Заклучок:''' После извлекување на сите парцијални зависности (FD2, FD3, FD4, FD10, FD12, FD14, FD16, FD17), универзалната релација е целосно декомпонирана. Примарниот клуч на Universal_Relation_Shifter_Base_8 е празно множество (∅), што значи дека таа релација повеќе не постои како валидна релација.
    801 Останатите функционални зависности (FD1, FD5-FD9, FD11, FD13, FD15) **нарушуваат 3NF** бидејќи нивните детерминанти (user_id, course_id, enrollment_id, итн.) не се примарни клучеви на
     845Останатите функционални зависности (FD1, FD5-FD9, FD11, FD13, FD15, FD19, FD31) **нарушуваат 3NF** бидејќи нивните детерминанти (user_id, course_id, enrollment_id, account_id, language_id, итн.) не се примарни клучеви на
    802846Universal_Relation_Shifter_Base_8, туку се независни детерминанти кои треба да формираат посебни релации.
    803847
     
    805849
    806850{{{
    807 User(user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points)
     851User(user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, account_id)
    808852   PK: user_id
    809853
    810 Universal_Relation_Shifter_Base_9 = Universal_Relation_Shifter_Base_8 - {user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points}
     854Universal_Relation_Shifter_Base_9 = Universal_Relation_Shifter_Base_8 - {user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points}
    811855
    812856Universal_Relation_Shifter_Base_9(
    813 expert_id,
     857account_id, account_email, account_password_hash, account_name,
     858language_id, language_value,
    814859course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price,
    815 course_version_id, version_number, version_creation_date, version_active,
     860course_version_id, version_number, version_created_at, version_is_active,
    816861enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    817862payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    824869
    825870'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id
    826  
    827 '''Проверка за dependency preservation:''' FD1 е зачувана во User
     871 
     872'''Проверка за dependency preservation:''' FD1 и FD18 се зачувани во User
    828873
    829874=== Чекор 6.2: Декомпозиција по FD5 (course_id → course_*) ===
     
    836881
    837882Universal_Relation_Shifter_Base_10(
    838 expert_id,
    839 course_version_id, version_number, version_creation_date, version_active,
     883account_id, account_email, account_password_hash, account_name,
     884language_id, language_value,
     885course_version_id, version_number, version_created_at, version_is_active,
    840886enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date,
    841887payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    848894
    849895'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id → course_version_id
    850  
     896 
    851897'''Проверка за dependency preservation:''' FD5 е зачувана во Course
    852898
     
    854900
    855901{{{
    856 Enrollment(enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id, payment_id, review_id)
     902Enrollment(enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id)
    857903   PK: enrollment_id
    858904
     
    860906
    861907Universal_Relation_Shifter_Base_11(
    862 expert_id,
    863 course_version_id, version_number, version_creation_date, version_active,
     908account_id, account_email, account_password_hash, account_name,
     909language_id, language_value,
     910course_version_id, version_number, version_created_at, version_is_active,
    864911enrollment_id,
    865912payment_id, payment_amount, payment_date, payment_method, payment_status,
     
    871918}}}
    872919
     920'''Забелешка:''' payment_id и review_id се дел од десната страна на FD6 (заради ограничувањата `uq_payment_enrollment` и `uq_review_enrollment`), но не се внесуваат како атрибути во Enrollment. Наместо тоа, врската се чува преку enrollment_id во Payment и Review, што ја избегнува циклична зависност помеѓу трите релации.
     921
    873922'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id
    874  
     923 
    875924'''Проверка за dependency preservation:''' FD6 е зачувана во Enrollment
    876925
     
    881930   PK: payment_id
    882931
    883 Universal_Relation_Shifter_Base_12 = Universal_Relation_Shifter_Base_11 - {payment_amount, payment_date, payment_method, payment_status}
     932Universal_Relation_Shifter_Base_12 = Universal_Relation_Shifter_Base_11 - {payment_id, payment_amount, payment_date, payment_method, payment_status}
    884933
    885934Universal_Relation_Shifter_Base_12(
    886 expert_id,
    887 course_version_id, version_number, version_creation_date, version_active,
     935account_id, account_email, account_password_hash, account_name,
     936language_id, language_value,
     937course_version_id, version_number, version_created_at, version_is_active,
    888938enrollment_id,
    889939review_id, review_rating, review_comment, review_date,
     
    895945
    896946'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id
    897  
     947 
    898948'''Проверка за dependency preservation:''' FD7 е зачувана во Payment
    899949
     
    904954   PK: review_id
    905955
    906 Universal_Relation_Shifter_Base_13 = Universal_Relation_Shifter_Base_12 - {review_rating, review_comment, review_date}
     956Universal_Relation_Shifter_Base_13 = Universal_Relation_Shifter_Base_12 - {review_id, review_rating, review_comment, review_date}
    907957
    908958Universal_Relation_Shifter_Base_13(
    909 expert_id,
    910 course_version_id, version_number, version_creation_date, version_active,
     959account_id, account_email, account_password_hash, account_name,
     960language_id, language_value,
     961course_version_id, version_number, version_created_at, version_is_active,
    911962enrollment_id,
    912963course_content_id, content_position,
     
    917968
    918969'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id
    919  
     970 
    920971'''Проверка за dependency preservation:''' FD8 е зачувана во Review
    921972
     
    929980
    930981Universal_Relation_Shifter_Base_14(
    931 expert_id,
    932 course_version_id, version_number, version_creation_date, version_active,
     982account_id, account_email, account_password_hash, account_name,
     983language_id, language_value,
     984course_version_id, version_number, version_created_at, version_is_active,
    933985enrollment_id,
    934986course_content_id, content_position,
     
    939991
    940992'''Проверка за lossless join:''' Може да се реконструира преку tag_id
    941  
     993 
    942994'''Проверка за dependency preservation:''' FD9 е зачувана во Tag
    943995
     
    945997
    946998{{{
    947 Course_Version(course_version_id, version_number, version_creation_date, version_active, course_id)
     999Course_Version(course_version_id, version_number, version_created_at, version_is_active, course_id)
    9481000   PK: course_version_id
    9491001
    950 Universal_Relation_Shifter_Base_15 = Universal_Relation_Shifter_Base_14 - {course_version_id, version_number, version_creation_date, version_active}
     1002Universal_Relation_Shifter_Base_15 = Universal_Relation_Shifter_Base_14 - {course_version_id, version_number, version_created_at, version_is_active}
    9511003
    9521004Universal_Relation_Shifter_Base_15(
    953 expert_id,
     1005account_id, account_email, account_password_hash, account_name,
     1006language_id, language_value,
    9541007enrollment_id,
    9551008course_content_id, content_position,
     
    9601013
    9611014'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id
    962  
    963 '''Проверка за dependency preservation:''' FD11 е зачувана во Course_Version
     1015 
     1016'''Проверка за dependency preservation:''' FD11 и FD20 се зачувани во Course_Version
    9641017
    9651018=== Чекор 6.8: Декомпозиција по FD13 (course_content_id → course_content_*) ===
     
    9721025
    9731026Universal_Relation_Shifter_Base_16(
    974 expert_id,
     1027account_id, account_email, account_password_hash, account_name,
     1028language_id, language_value,
    9751029enrollment_id,
    9761030course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type,
     
    9801034
    9811035'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id → course_version_id
    982  
    983 '''Проверка за dependency preservation:''' FD13 е зачувана во Course_Content
     1036 
     1037'''Проверка за dependency preservation:''' FD13 и FD26 се зачувани во Course_Content
    9841038
    9851039=== Чекор 6.9: Декомпозиција по FD15 (course_lecture_id → course_lecture_*) ===
     
    9921046
    9931047Universal_Relation_Shifter_Base_17(
    994 expert_id,
     1048account_id, account_email, account_password_hash, account_name,
     1049language_id, language_value,
    9951050enrollment_id,
    9961051tag_id
     
    9991054
    10001055'''Проверка за lossless join:''' Може да се реконструира преку enrollment_id → course_version_id → course_content_id
    1001  
    1002 '''Проверка за dependency preservation:''' FD15 е зачувана во Course_Lecture
    1003 
    1004 === Анализа на Universal_Relation_Shifter_Base_17 ===
    1005 
    1006 {{{
    1007 Universal_Relation_Shifter_Base_17(
    1008 expert_id,
     1056 
     1057'''Проверка за dependency preservation:''' FD15 и FD27 се зачувани во Course_Lecture
     1058
     1059=== Чекор 6.10: Декомпозиција по FD19 (account_id → account_*) ===
     1060
     1061{{{
     1062Account(account_id, account_email, account_password_hash, account_name)
     1063   PK: account_id
     1064
     1065Universal_Relation_Shifter_Base_18 = Universal_Relation_Shifter_Base_17 - {account_id, account_email, account_password_hash, account_name}
     1066
     1067Universal_Relation_Shifter_Base_18(
     1068language_id, language_value,
    10091069enrollment_id,
    10101070tag_id
     
    10121072}}}
    10131073
    1014 
    1015 Universal_Relation_Shifter_Base_17 претставува колекција од foreign keys кои треба да се организираат во посебни many-to-many junction tables.
     1074'''Проверка за lossless join:''' Може да се реконструира преку account_id во User и Expert
     1075 
     1076'''Проверка за dependency preservation:''' FD19 и FD30 се зачувани во Account
     1077
     1078=== Чекор 6.11: Декомпозиција по FD31 (language_id → language_value) ===
     1079
     1080{{{
     1081Language(language_id, language_value)
     1082   PK: language_id
     1083
     1084Universal_Relation_Shifter_Base_19 = Universal_Relation_Shifter_Base_18 - {language_id, language_value}
     1085
     1086Universal_Relation_Shifter_Base_19(
     1087enrollment_id,
     1088tag_id
     1089)
     1090}}}
     1091
     1092'''Проверка за lossless join:''' Може да се реконструира преку language_id во релациите за преводи
     1093 
     1094'''Проверка за dependency preservation:''' FD31 и FD32 се зачувани во Language
     1095
     1096=== Анализа на Universal_Relation_Shifter_Base_19 ===
     1097
     1098{{{
     1099Universal_Relation_Shifter_Base_19(
     1100enrollment_id,
     1101tag_id
     1102)
     1103}}}
     1104
     1105
     1106Universal_Relation_Shifter_Base_19 претставува колекција од foreign keys кои треба да се организираат во посебни many-to-many junction tables.
    10161107
    10171108'''Прашање:''' Дали оваа релација има семантичка смисла?
    1018 '''Одговор:''' НЕ! Universal_Relation_Shifter_Base_17 е само технички резултат од декомпозициите и не претставува ниеден реален бизнис концепт.
     1109'''Одговор:''' НЕ! Universal_Relation_Shifter_Base_19 е само технички резултат од декомпозициите и не претставува ниеден реален бизнис концепт.
    10191110
    10201111'''Заклучок од 3NF:'''
    1021 Сите функционални зависности (FD1-FD27) се организирани во релации кои се во 3NF. Universal_Relation_Shifter_Base_17 повеќе не постои како валидна релација.
     1112Сите функционални зависности (FD1-FD33) се организирани во релации кои се во 3NF. Universal_Relation_Shifter_Base_19 повеќе не постои како валидна релација.
    10221113
    10231114'''Останати врски (many-to-many):'''
    1024 Foreign keys во Universal_Relation_Shifter_Base_17 укажуваат на many-to-many релации кои НЕ се дефинирани преку функционални зависности, туку преку бизнис логика:
     1115Преостанатите foreign keys, заедно со експертот и курсот извлечени во претходните чекори, укажуваат на many-to-many релации кои НЕ се дефинирани преку функционални зависности, туку преку бизнис логика:
    10251116
    10261117* '''User_Tag'''(user_id, tag_id) - корисник има интереси
     
    10321123'''Релации креирани преку FD декомпозиција:'''
    10331124
    1034 '''1NF Декомпозиција (1 релација):'''
     1125'''1NF Декомпозиција (2 релации):'''
    10351126||= Релација =||= Атрибути =||= Примарен клуч =||
    1036 || Course_What_Will_Be_Learned || course_translate_id, course_what_will_be_learned || (course_translate_id, course_what_will_be_learned) ||
    1037 || User_Course_Favorite_Id || user_id, user_course_favorite_id || (user_id, user_course_favorite_id) ||
     1127|| Course_Translate_What_Will_Be_Learned || course_translate_id, course_what_will_be_learned || (course_translate_id, course_what_will_be_learned) ||
     1128|| User_Favorite_Course || user_id, course_id || (user_id, course_id) ||
    10381129
    10391130'''2NF Декомпозиција (8 релации):'''
    10401131||= Релација =||= Атрибути =||= Примарен клуч =||
    1041 || Verification_Token || verification_token_uuid, token_created_at, token_expired_at, user_id || verification_token_uuid ||
     1132|| Verification_Token || verification_token_uuid, token_created_at, token_expires_at, user_id || verification_token_uuid ||
    10421133|| Meeting_Reminder || meeting_reminder_id, meeting_at, meeting_scheduled_at, meeting_sent, meeting_link, user_id || meeting_reminder_id ||
    1043 || Expert || expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash || expert_id ||
    1044 || Tag_Translate || tag_translate_id, tag_translate_language, tag_value, tag_id || tag_translate_id ||
    1045 || Course_Translate || course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id || course_translate_id ||
    1046 || Course_Content_Translate || course_content_translate_id, content_translate_title, content_translate_language, course_content_id || course_content_translate_id ||
    1047 || Course_Lecture_Translate || course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id || course_lecture_translate_id ||
    1048 || User_Course_Progress || user_course_progress_id, progress_completed, progress_completed_at, enrollment_id, course_lecture_id || user_course_progress_id ||
    1049 
    1050 '''3NF Декомпозиција (9 релации):'''
     1134|| Expert || expert_id, account_id || expert_id ||
     1135|| Tag_Translate || tag_translate_id, tag_value, tag_id, language_id || tag_translate_id ||
     1136|| Course_Translate || course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id || course_translate_id ||
     1137|| Course_Content_Translate || course_content_translate_id, content_translate_title, course_content_id, language_id || course_content_translate_id ||
     1138|| Course_Lecture_Translate || course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id || course_lecture_translate_id ||
     1139|| User_Course_Progress || user_course_progress_id, progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id || user_course_progress_id ||
     1140
     1141'''3NF Декомпозиција (11 релации):'''
    10511142||= Релација =||= Атрибути =||= Примарен клуч =||
    1052 || User || user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points || user_id ||
     1143|| Account || account_id, account_email, account_password_hash, account_name || account_id ||
     1144|| User || user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, account_id || user_id ||
     1145|| Language || language_id, language_value || language_id ||
    10531146|| Course || course_id, course_image_url, course_color, course_difficulty, course_duration_minutes, course_price || course_id ||
    1054 || Course_Version || course_version_id, version_number, version_creation_date, version_active, course_id || course_version_id ||
    1055 || Enrollment || enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id, payment_id, review_id || enrollment_id ||
     1147|| Course_Version || course_version_id, version_number, version_created_at, version_is_active, course_id || course_version_id ||
     1148|| Enrollment || enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id || enrollment_id ||
    10561149|| Payment || payment_id, payment_amount, payment_date, payment_method, payment_status, enrollment_id || payment_id ||
    10571150|| Review || review_id, review_rating, review_comment, review_date, enrollment_id || review_id ||
     
    10741167За секоја релација проверуваме: за секоја нетривијална FD X → Y, дали X е суперклуч?
    10751168
     1169==== Account ====
     1170
     1171||= FD =||= Детерминант =||= Суперклуч? =||
     1172|| account_id → сите || account_id || ✓ ДА ||
     1173|| account_email → сите (FD30) || account_email || ✓ ДА ||
     1174
     1175'''Account е во BCNF''' ✓
     1176
     1177==== Language ====
     1178
     1179||= FD =||= Детерминант =||= Суперклуч? =||
     1180|| language_id → сите || language_id || ✓ ДА ||
     1181|| language_value → сите (FD32) || language_value || ✓ ДА ||
     1182
     1183'''Language е во BCNF''' ✓
     1184
    10761185==== Verification_Token ====
    10771186
     
    10851194||= FD =||= Детерминант =||= Суперклуч? =||
    10861195|| meeting_reminder_id → сите || meeting_reminder_id || ✓ ДА ||
     1196|| meeting_link → сите (FD33) || meeting_link || ✓ ДА ||
    10871197
    10881198'''Meeting_Reminder е во BCNF''' ✓
     
    10991209||= FD =||= Детерминант =||= Суперклуч? =||
    11001210|| tag_translate_id → сите || tag_translate_id || ✓ ДА ||
     1211|| (tag_id, language_id) → сите (FD24) || tag_id, language_id || ✓ ДА ||
    11011212
    11021213'''Tag_Translate е во BCNF''' ✓
     
    11061217||= FD =||= Детерминант =||= Суперклуч? =||
    11071218|| course_translate_id → сите || course_translate_id || ✓ ДА ||
     1219|| (course_id, language_id) → сите (FD21) || course_id, language_id || ✓ ДА ||
    11081220
    11091221'''Course_Translate е во BCNF''' ✓
     
    11131225||= FD =||= Детерминант =||= Суперклуч? =||
    11141226|| course_content_translate_id → сите || course_content_translate_id || ✓ ДА ||
     1227|| (course_content_id, language_id) → сите (FD23) || course_content_id, language_id || ✓ ДА ||
    11151228
    11161229'''Course_Content_Translate е во BCNF''' ✓
     
    11201233||= FD =||= Детерминант =||= Суперклуч? =||
    11211234|| course_lecture_translate_id → сите || course_lecture_translate_id || ✓ ДА ||
     1235|| (course_lecture_id, language_id) → сите (FD22) || course_lecture_id, language_id || ✓ ДА ||
    11221236
    11231237'''Course_Lecture_Translate е во BCNF''' ✓
     
    11271241||= FD =||= Детерминант =||= Суперклуч? =||
    11281242|| user_course_progress_id → сите || user_course_progress_id || ✓ ДА ||
     1243|| (enrollment_id, course_lecture_id) → сите (FD25) || enrollment_id, course_lecture_id || ✓ ДА ||
    11291244
    11301245'''User_Course_Progress е во BCNF''' ✓
     
    11341249||= FD =||= Детерминант =||= Суперклуч? =||
    11351250|| user_id → сите || user_id || ✓ ДА ||
     1251|| user_email → сите (FD18) || user_email || ✓ ДА ||
    11361252
    11371253'''User е во BCNF''' ✓
     
    11551271||= FD =||= Детерминант =||= Суперклуч? =||
    11561272|| payment_id → сите || payment_id || ✓ ДА ||
     1273|| enrollment_id → сите (FD6) || enrollment_id || ✓ ДА ||
    11571274
    11581275'''Payment е во BCNF''' ✓
     
    11621279||= FD =||= Детерминант =||= Суперклуч? =||
    11631280|| review_id → сите || review_id || ✓ ДА ||
     1281|| enrollment_id → сите (FD6) || enrollment_id || ✓ ДА ||
    11641282
    11651283'''Review е во BCNF''' ✓
     
    11761294||= FD =||= Детерминант =||= Суперклуч? =||
    11771295|| course_version_id → сите || course_version_id || ✓ ДА ||
     1296|| (course_id, version_number) → сите (FD20) || course_id, version_number || ✓ ДА ||
    11781297
    11791298'''Course_Version е во BCNF''' ✓
     
    11831302||= FD =||= Детерминант =||= Суперклуч? =||
    11841303|| course_content_id → сите || course_content_id || ✓ ДА ||
     1304|| (course_version_id, content_position) → сите (FD26) || course_version_id, content_position || ✓ ДА ||
    11851305
    11861306'''Course_Content е во BCNF''' ✓
     
    11901310||= FD =||= Детерминант =||= Суперклуч? =||
    11911311|| course_lecture_id → сите || course_lecture_id || ✓ ДА ||
     1312|| (course_content_id, lecture_position) → сите (FD27) || course_content_id, lecture_position || ✓ ДА ||
    11921313
    11931314'''Course_Lecture е во BCNF''' ✓
     
    12031324
    12041325{{{
    1205 User_Course_Favorite_Id(user_id, user_course_favorite_id)
    1206   - Примарен клуч: user_id, user_course_favorite_id
    1207   - Кандидат клучеви: user_id, user_course_favorite_id
    1208   - Надворешни клучеви: user_id
    1209 
    1210 Course_What_Will_Be_Learned(course_translate_id, course_what_will_be_learned)
     1326User_Favorite_Course(user_id, course_id)
     1327  - Примарен клуч: user_id, course_id
     1328  - Кандидат клучеви: user_id, course_id
     1329  - Надворешни клучеви: user_id, course_id
     1330
     1331Course_Translate_What_Will_Be_Learned(course_translate_id, course_what_will_be_learned)
    12111332  - Примарен клуч: course_translate_id, course_what_will_be_learned
    12121333  - Кандидат клучеви: course_translate_id, course_what_will_be_learned
    12131334  - Надворешни клучеви: course_translate_id
    12141335
    1215 User(user_id, user_name, user_email, user_login_provider, user_password_hash, user_verified, user_profile_complete, user_used_free_consultation, user_company_size, user_work_position, user_points)
     1336Account(account_id, account_email, account_password_hash, account_name)
     1337  - Примарен клуч: account_id
     1338  - Кандидат клучеви: account_id, account_email
     1339  - Надворешни клучеви: -
     1340
     1341User(user_id, user_name, user_email, user_login_provider, user_password_hash, user_is_verified, user_is_profile_complete, user_has_used_free_consultation, user_company_size, user_work_position, user_points, account_id)
    12161342  - Примарен клуч: user_id
    1217   - Кандидат клучеви: user_id, user_email
     1343  - Кандидат клучеви: user_id, user_email, account_id
     1344  - Надворешни клучеви: account_id
     1345
     1346Expert(expert_id, account_id)
     1347  - Примарен клуч: expert_id
     1348  - Кандидат клучеви: expert_id, account_id
     1349  - Надворешни клучеви: account_id
     1350
     1351Language(language_id, language_value)
     1352  - Примарен клуч: language_id
     1353  - Кандидат клучеви: language_id, language_value
    12181354  - Надворешни клучеви: -
    12191355
    1220 Expert(expert_id, expert_name, expert_email, expert_login_provider, expert_password_hash)
    1221   - Примарен клуч: expert_id
    1222   - Кандидат клучеви: expert_id, expert_email
    1223   - Надворешни клучеви: -
    1224 
    1225 Verification_Token(verification_token_uuid, token_created_at, token_expired_at, user_id)
     1356Verification_Token(verification_token_uuid, token_created_at, token_expires_at, user_id)
    12261357  - Примарен клуч: verification_token_uuid
    12271358  - Кандидат клучеви: verification_token_uuid
     
    12331364  - Надворешни клучеви: user_id
    12341365
    1235 Enrollment(enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id, payment_id, review_id)
     1366Enrollment(enrollment_id, enrollment_status, enrollment_purchase_date, enrollment_activation_date, enrollment_completion_date, user_id, course_version_id)
    12361367  - Примарен клуч: enrollment_id
    1237   - Кандидат клучеви: enrollment_id
    1238   - Надворешни клучеви: user_id, course_version_id, payment_id, review_id
     1368  - Кандидат клучеви: enrollment_id, (user_id, course_version_id)
     1369  - Надворешни клучеви: user_id, course_version_id
    12391370
    12401371Payment(payment_id, payment_amount, payment_date, payment_method, payment_status, enrollment_id)
    12411372  - Примарен клуч: payment_id
    1242   - Кандидат клучеви: payment_id
     1373  - Кандидат клучеви: payment_id, enrollment_id
    12431374  - Надворешни клучеви: enrollment_id
    12441375
    12451376Review(review_id, review_rating, review_comment, review_date, enrollment_id)
    12461377  - Примарен клуч: review_id
    1247   - Кандидат клучеви: review_id
     1378  - Кандидат клучеви: review_id, enrollment_id
    12481379  - Надворешни клучеви: enrollment_id
    12491380
    1250 Course_Version(course_version_id, version_number, version_creation_date, version_active, course_id)
     1381Course_Version(course_version_id, version_number, version_created_at, version_is_active, course_id)
    12511382  - Примарен клуч: course_version_id
    1252   - Кандидат клучеви: course_version_id
     1383  - Кандидат клучеви: course_version_id, (course_id, version_number)
    12531384  - Надворешни клучеви: course_id
    12541385
     
    12581389  - Надворешни клучеви: -
    12591390
    1260 Course_Translate(course_translate_id, course_translate_language, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id)
     1391Course_Translate(course_translate_id, course_title_short, course_title, course_description_short, course_description, course_description_long, course_id, language_id)
    12611392  - Примарен клуч: course_translate_id
    1262   - Кандидат клучеви: course_translate_id
    1263   - Надворешни клучеви: course_id
     1393  - Кандидат клучеви: course_translate_id, (course_id, language_id)
     1394  - Надворешни клучеви: course_id, language_id
    12641395
    12651396Course_Content(course_content_id, content_position, course_version_id)
    12661397  - Примарен клуч: course_content_id
    1267   - Кандидат клучеви: course_content_id
     1398  - Кандидат клучеви: course_content_id, (course_version_id, content_position)
    12681399  - Надворешни клучеви: course_version_id
    12691400
    1270 Course_Content_Translate(course_content_translate_id, content_translate_title, content_translate_language, course_content_id)
     1401Course_Content_Translate(course_content_translate_id, content_translate_title, course_content_id, language_id)
    12711402  - Примарен клуч: course_content_translate_id
    1272   - Кандидат клучеви: course_content_translate_id
    1273   - Надворешни клучеви: course_content_id
     1403  - Кандидат клучеви: course_content_translate_id, (course_content_id, language_id)
     1404  - Надворешни клучеви: course_content_id, language_id
    12741405
    12751406Course_Lecture(course_lecture_id, lecture_duration_minutes, lecture_position, lecture_content_type, course_content_id)
    12761407  - Примарен клуч: course_lecture_id
    1277   - Кандидат клучеви: course_lecture_id
     1408  - Кандидат клучеви: course_lecture_id, (course_content_id, lecture_position)
    12781409  - Надворешни клучеви: course_content_id
    12791410
    1280 Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_language, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id)
     1411Course_Lecture_Translate(course_lecture_translate_id, lecture_title, lecture_content_file_name, lecture_description, lecture_content_text, course_lecture_id, language_id)
    12811412  - Примарен клуч: course_lecture_translate_id
    1282   - Кандидат клучеви: course_lecture_translate_id
    1283   - Надворешни клучеви: course_lecture_id
    1284 
    1285 User_Course_Progress(user_course_progress_id, progress_completed, progress_completed_at, enrollment_id, course_lecture_id)
     1413  - Кандидат клучеви: course_lecture_translate_id, (course_lecture_id, language_id)
     1414  - Надворешни клучеви: course_lecture_id, language_id
     1415
     1416User_Course_Progress(user_course_progress_id, progress_is_completed, progress_completed_at, enrollment_id, course_lecture_id)
    12861417  - Примарен клуч: user_course_progress_id
    1287   - Кандидат клучеви: user_course_progress_id
     1418  - Кандидат клучеви: user_course_progress_id, (enrollment_id, course_lecture_id)
    12881419  - Надворешни клучеви: enrollment_id, course_lecture_id
    12891420
     
    12931424  - Надворешни клучеви: -
    12941425
    1295 Tag_Translate(tag_translate_id, tag_translate_language, tag_value, tag_id)
     1426Tag_Translate(tag_translate_id, tag_value, tag_id, language_id)
    12961427  - Примарен клуч: tag_translate_id
    1297   - Кандидат клучеви: tag_translate_id
    1298   - Надворешни клучеви: tag_id
     1428  - Кандидат клучеви: tag_translate_id, (tag_id, language_id)
     1429  - Надворешни клучеви: tag_id, language_id
    12991430
    13001431User_Tag(user_id, tag_id)
     
    13161447=== 8.2 Дискусија на разликите од моделот во Фаза P2 ===
    13171448
    1318 Преку процесот на нормализација, тргнувајќи од една универзална релација, дојдовме до '''22 релации'''
    1319 (17 од функционални зависности + 3 many-to-many junction tables + 2 multi-value tables). Споредбата со концептуалниот модел
     1449Преку процесот на нормализација, тргнувајќи од една универзална релација, дојдовме до '''24 релации'''
     1450(19 од функционални зависности + 3 many-to-many junction tables + 2 multi-value tables). Споредбата со концептуалниот модел
    13201451од Фаза P2 покажува следно:
    13211452
     
    13251456
    13261457 1. '''User''' - идентична структура и атрибути
    1327  2. '''Expert''' - идентична структура и атрибути
    1328  3. '''Course''' - идентична структура и атрибути
    1329  4. '''Course_Version''' - идентична структура и атрибути
    1330  5. '''Enrollment''' - идентична структура и атрибути
    1331  6. '''Payment''' - идентична структура и атрибути (one-to-one со Enrollment)
    1332  7. '''Review''' - идентична структура и атрибути (one-to-one со Enrollment)
    1333  8. '''Tag''' - идентична структура и атрибути
    1334  9. '''Course_Translate''' - идентична структура и атрибути
    1335  10. '''Course_Content''' - идентична структура и атрибути
    1336  11. '''Course_Content_Translate''' - идентична структура и атрибути
    1337  12. '''Course_Lecture''' - идентична структура и атрибути
    1338  13. '''Course_Lecture_Translate''' - идентична структура и атрибути
    1339  14. '''Tag_Translate''' - идентична структура и атрибути
    1340  15. '''Verification_Token''' - идентична структура и атрибути
    1341  16. '''Meeting_Reminder''' - идентична структура и атрибути
    1342  17. '''User_Course_Progress''' - идентична структура и атрибути
     1458 2. '''Course''' - идентична структура и атрибути
     1459 3. '''Course_Version''' - идентична структура и атрибути
     1460 4. '''Enrollment''' - идентична структура и атрибути
     1461 5. '''Payment''' - идентична структура и атрибути (one-to-one со Enrollment)
     1462 6. '''Review''' - идентична структура и атрибути (one-to-one со Enrollment)
     1463 7. '''Tag''' - идентична структура и атрибути
     1464 8. '''Course_Translate''' - идентична структура и атрибути
     1465 9. '''Course_Content''' - идентична структура и атрибути
     1466 10. '''Course_Content_Translate''' - идентична структура и атрибути
     1467 11. '''Course_Lecture''' - идентична структура и атрибути
     1468 12. '''Course_Lecture_Translate''' - идентична структура и атрибути
     1469 13. '''Tag_Translate''' - идентична структура и атрибути
     1470 14. '''Verification_Token''' - идентична структура и атрибути
     1471 15. '''Meeting_Reminder''' - идентична структура и атрибути
     1472 16. '''User_Course_Progress''' - идентична структура и атрибути
     1473
     1474==== Релации кои се разликуваат од P2 ====
     1475
     1476 17. '''Account''' - нова релација која не постоеше во концептуалниот модел. Атрибутите за најава (email, password_hash, name) беа дуплирани во User и Expert, па се издвоени во заеднички ентитет.
     1477 18. '''Expert''' - се разликува од P2. Атрибутите expert_name, expert_email, expert_login_provider и expert_password_hash преминаа во Account, па Expert останува само со expert_id и надворешниот клуч account_id.
     1478 19. '''Language''' - нова релација која не постоеше во концептуалниот модел. Јазикот беше текстуален атрибут во четирите релации за преводи, а сега е самостоен ентитет со надворешни клучеви language_id.
    13431479
    13441480==== Many-to-Many релации ====
    13451481
    1346  18. '''Expert_Course''' - junction table за many-to-many релација помеѓу Expert и Course
    1347  19. '''Course_Tag''' - junction table за many-to-many релација помеѓу Course и Tag
    1348  20. '''User_Tag''' - junction table за many-to-many релација помеѓу User и Tag
     1482 20. '''Expert_Course''' - junction table за many-to-many релација помеѓу Expert и Course
     1483 21. '''Course_Tag''' - junction table за many-to-many релација помеѓу Course и Tag
     1484 22. '''User_Tag''' - junction table за many-to-many релација помеѓу User и Tag
    13491485
    13501486==== Релација со мултивредносен атрибут ====
    13511487
    1352  21. '''Course_What_Will_Be_Learned''' - беше дел од Course_Translate во концептуалниот модел, но се издвои во посебна релација во 1NF декомпозицијата поради мултивредносна природа (еден курс има повеќе "what will be learned" ставки).
    1353  22. '''User_Course_Favorite_Id''' - беше дел од User во концептуалниот модел, но се издвои во посебна релација во 1NF декомпозицијата поради мултивредносна природа (еден корисник има повеќе "course favorite id" ставки).
     1488 23. '''Course_Translate_What_Will_Be_Learned''' - беше дел од Course_Translate во концептуалниот модел, но се издвои во посебна релација во 1NF декомпозицијата поради мултивредносна природа (еден превод на курс има повеќе "what will be learned" ставки).
     1489 24. '''User_Favorite_Course''' - беше дел од User во концептуалниот модел, но се издвои во посебна релација во 1NF декомпозицијата поради мултивредносна природа (еден корисник има повеќе омилени курсеви).
    13541490
    13551491==== Клучни наоди ====
    13561492
    1357  1. '''Процесот на нормализација го потврди дизајнот''' - секоја декомпозиција базирана на функционалните зависности резултираше со релација која одговара на ентитет од оригиналниот модел.
    1358 
    1359  2. '''Клучот на универзалната релација''' - примарниот клуч беше идентификуван како композитен клуч од 8 атрибути: {verification_token_uuid, meeting_reminder_id, user_course_progress_id, expert_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id, course_what_will_be_learned}. Овој клуч беше идентификуван преку анализа на функционалните зависности и класификација лева/десна страна на атрибутите.
     1493 1. '''Процесот на нормализација го потврди најголемиот дел од дизајнот''' - секоја декомпозиција базирана на функционалните зависности резултираше со релација која одговара на ентитет од оригиналниот модел, освен во три случаи: Account, Language и намалениот Expert.
     1494
     1495 2. '''Клучот на универзалната релација''' - примарниот клуч беше идентификуван како композитен клуч од 10 атрибути: {verification_token_uuid, meeting_reminder_id, expert_id, course_what_will_be_learned, user_favorite_course_ids, user_course_progress_id, course_lecture_translate_id, course_content_translate_id, course_translate_id, tag_translate_id}. Овој клуч беше идентификуван преку анализа на функционалните зависности и класификација лева/десна страна на атрибутите. По 1NF декомпозицијата, атрибутите course_what_will_be_learned и user_favorite_course_ids се извлекуваат, па клучот на базната релација се сведува на 8 атрибути.
    13601496
    13611497 3. '''Декомпозицијата е lossless''' - на секој чекор од процесот на нормализација, оригиналната информација може да се реконструира преку JOIN операции на заедничките атрибути (foreign keys).
    13621498
    1363  4. '''Сите функционални зависности се зачувани''' - сите 29 функционални зависности (FD1-FD29) се зачувани во соодветните релации, што значи дека ограничувањата можат да се проверуваат без потреба од скапи JOIN операции.
     1499 4. '''Сите функционални зависности се зачувани''' - сите 33 функционални зависности (FD1-FD33) се зачувани во соодветните релации, што значи дека ограничувањата можат да се проверуваат без потреба од скапи JOIN операции.
    13641500
    13651501 5. '''Many-to-many релации''' - junction tables (Expert_Course, Course_Tag, User_Tag) не произлегуваат од функционални зависности, туку од ER моделот и бизнис логиката. Овие релации немаат свои атрибути освен composite primary key од два foreign keys.
    13661502
     1503 6. '''Издвојувањето на Account''' - оваа релација произлезе од функционалните зависности FD19 и FD30, кои не постоеја во P2. Во P2 атрибутите за најава беа дуплирани во User и Expert, што претставува редундантност: промена на лозинка би барала ажурирање на две релации.
     1504
    13671505==== Заклучок ====
    13681506
    1369 Процесот на нормализација '''целосно го потврди дизајнот''' од концептуалната фаза (P2). Ова покажува дека оригиналниот ER модел беше креиран според принципите на добра база на податоци (минимална редундантност, јасна сепарација на концепти, правилна идентификација на ентитети и релации).
    1370 
    1371 '''Финалниот релационен модел ќе биде идентичен со моделот од Фаза P2'''.
     1507Процесот на нормализација '''го потврди најголемиот дел од дизајнот''' од концептуалната фаза (P2), но воведе и три разлики: издвојување на Account, издвојување на Language и намалување на Expert. Ова покажува дека оригиналниот ER модел беше во голема мера креиран според принципите на добра база на податоци (минимална редундантност, јасна сепарација на концепти, правилна идентификација на ентитети и релации), но дека дуплираните атрибути за најава и текстуалниот атрибут за јазик беа извори на редундантност кои нормализацијата ги отстрани.
     1508
     1509'''Финалниот релационен модел се разликува од моделот од Фаза P2 во три релации: Account, Language и Expert'''.