Changes between Version 7 and Version 8 of ERModel
- Timestamp:
- 09/02/26 01:56:20 (5 days ago)
Legend:
- Unmodified
- Added
- Removed
- Modified
-
ERModel
v7 v8 1 = Entity-Relationship Model v. 09=1 = Entity-Relationship Model v.10 = 2 2 == Diagram == 3 3 4 [[Image(wiki:ERModel:ERModel_v 09.png)]]4 [[Image(wiki:ERModel:ERModel_v10.png)]] 5 5 == Data requirements == 6 6 … … 11 11 Students represents UKIM students known to the system, including external participants and students who later become BEST Skopje members. It is modeled as the root person entity because every member is also a student, but not every student is necessarily a member. The entity is needed so that applications, activity participation, and membership can all refer to the same student record. 12 12 13 * '''Candidate keys:''' index is chosen as the primary key because the project is scoped to UKIM students and the student index uniquely identifies a student in this context.14 * '''Attributes:''' 15 * index: numeric/textidentifier, required, unique.13 * '''Candidate keys:''' student_index is chosen as the primary key because the project is scoped to UKIM students and the student index uniquely identifies a student in this context. 14 * '''Attributes:''' 15 * student_index: numeric identifier, required, unique. 16 16 * first_name: text, required. 17 17 * last_name: text, required. … … 27 27 Members represents students who are part of BEST Skopje. It is modeled as a specialization of Students because member records inherit the student data, while membership-specific information is represented through membership stages, mentorship, responsibilities, and organizational roles. This avoids duplicating personal data while allowing the system to distinguish ordinary event participants from members. 28 28 29 * '''Candidate keys:''' the primary key is inherited from Students, so index is used. 30 * '''Attributes:''' no direct attributes in the ER model. 29 * '''Candidate keys:''' the primary key is inherited from Students, so student_index is used. 31 30 32 31 ==== Observers ==== … … 34 33 Observers represents members in the observer/associate stage. It is modeled as a subtype of Members because observers are members with a specific membership status and possible future progression to young member. 35 34 36 * '''Candidate keys:''' inherited index from Members. 37 * '''Attributes:''' no direct attributes in the ER model. 35 * '''Candidate keys:''' inherited student_index from Members. 38 36 39 37 ==== !YoungMembers ==== 40 38 41 !YoungMembers represents members in the young member stage. It is modeled as a subtype of Members because young members are members with additional membership-development meaning, especially mentorship by a full member and later possible progression to full member. 42 43 * '''Candidate keys:''' inherited index from Members. 44 * '''Attributes:''' no direct attributes in the ER model. 39 !YoungMembers represents members in the young member stage. It is modeled as a subtype of Members because young members are members with additional membership-development meaning, especially mentorship by a full member and later possible progression to full member. 40 41 * '''Candidate keys:''' inherited student_index from Members. 45 42 46 43 ==== !FullMembers ==== … … 48 45 !FullMembers represents members with full membership rights and responsibilities. It is modeled as a subtype of Members because full members can mentor young members and hold organizational functions, including Board and non-Board roles. 49 46 50 * '''Candidate keys:''' inherited index from Members. 51 * '''Attributes:''' no direct attributes in the ER model. 47 * '''Candidate keys:''' inherited student_index from Members. 52 48 53 49 ==== Alumni ==== … … 55 51 Alumni represents former full members with alumni status. It is modeled as a subtype of Members because alumni are still relevant to BEST Skopje activities and history, but they are distinct from active observer, young, and full members. Their year of studies would be 0 if they've finished their studies. 56 52 57 * '''Candidate keys:''' inherited index from Members. 58 * '''Attributes:''' no direct attributes in the ER model. 53 * '''Candidate keys:''' inherited student_index from Members. 59 54 60 55 ==== !MembershipStages ==== … … 62 57 !MembershipStages stores the possible membership stages used in membership history, such as observer, young member, full member, and alumni. It is modeled separately even though the member subtypes exist because the has_stage relationship needs to store historical periods with valid_from and valid_to. 63 58 64 * '''Candidate keys:''' ms_name is chosen as the primary key because membership stage names are stable controlled values. 65 * '''Attributes:''' 59 * '''Candidate keys:''' ms_id and ms_name. ms_id is chosen as the primary key because membership stage names are text labels. ms_name is unique. 60 * '''Attributes:''' 61 * ms_id: numeric identifier, required, unique. 66 62 * ms_name: text, required, unique. 67 63 … … 70 66 !OrganizationalFunctions represents reusable organizational role types, such as President, Treasurer, Secretary, HR coordinator, FR coordinator, PR coordinator, IT coordinator, Design coordinator, Grants coordinator or Vivaldi coordinator. It is modeled separately from members because a function can be held by different full members in different mandates, and one full member can hold different functions over time. 71 67 72 * '''Candidate keys:''' of_title is chosen as the primary key because function titles are stable role names within the organization. 73 * '''Attributes:''' 68 * '''Candidate keys:''' of_id and of_title. of_id is chosen as the primary key because function titles are text labels. of_title is unique. 69 * '''Attributes:''' 70 * of_id: numeric identifier, required, unique. 74 71 * of_title: text, required, unique. 75 72 … … 78 75 Board represents organizational functions that are Board roles. It is modeled as a subtype of !OrganizationalFunctions because Board membership is treated as a role/function, not as a separate membership stadium. 79 76 80 * '''Candidate keys:''' inherited of_title from !OrganizationalFunctions. 81 * '''Attributes:''' no direct attributes in the ER model. 77 * '''Candidate keys:''' inherited of_id from !OrganizationalFunctions. 82 78 83 79 ==== !NonBoard ==== … … 85 81 !NonBoard represents organizational functions that are not Board roles, such as non-Board coordinators. It is modeled as a subtype of !OrganizationalFunctions so the model can distinguish Board and non-Board responsibilities while keeping both under the same function structure. 86 82 87 * '''Candidate keys:''' inherited of_title from !OrganizationalFunctions. 88 * '''Attributes:''' no direct attributes in the ER model. 83 * '''Candidate keys:''' inherited of_id from !OrganizationalFunctions. 89 84 90 85 ==== !ActivityTypes ==== 91 86 92 !ActivityTypes represents abstract categories of internal activities, such as weekly meetings, BEST Course in Summer meetings, working groups, workshops, FR calls, trainings, full member meetings, Board meetings, parties, alumni parties, informative meetings, and assemblies. It is modeled separately from activity sessions because many concrete sessions can occur for the same activity type. 93 94 * '''Candidate keys:''' at_name is chosen as the primary key because activity type names are controlled and unique. 95 * '''Attributes:''' 87 !ActivityTypes represents abstract categories of internal activities, such as weekly meetings, BEST Course in Summer meetings, working groups, workshops, FR calls, trainings, full member meetings, Board meetings, parties, alumni parties, and informative meetings. It is modeled separately from activity sessions because many concrete sessions can occur for the same activity type. 88 89 * '''Candidate keys:''' at_id and at_name. at_id is chosen as the primary key because activity type names are text labels. at_name is unique. 90 * '''Attributes:''' 91 * at_id: numeric identifier, required, unique. 96 92 * at_name: text, required, unique. 97 93 * at_description: text, required, explanation of what the activity type is used for. 98 94 95 ==== Locations ==== 96 97 Locations represents reusable places where event editions, event sessions, and activity sessions can happen. 98 99 * '''Candidate keys:''' l_id and l_name. l_id is chosen as the primary key because location names are text labels. l_name is unique. 100 * '''Attributes:''' 101 * l_id: numeric identifier, required, unique. 102 * l_name: text, required, unique. 103 99 104 ==== !ActivitySessions ==== 100 105 101 !ActivitySessions represents concrete occurrences of activity types. For example, one weekly meeting, one FR call, one IT workshop, or one training session is an activity session. It is modeled as a weak entity dependent on !ActivityTypes because a session is an instance of an abstract activity type and is identified in context by that type, start time, and location.102 103 * '''Candidate keys:''' the chosen primary key is the composite key at_name + as_start_time + as_location, where at_name comes from the owning !ActivityTypes entity and as_start_time and as_location are the partial keys.104 * '''Attributes:''' 105 * as_ start_time: datetime, required, valid future or past timestamp depending on whether the session is planned or completed.106 * as_ location: text, required, room/place/online location.106 !ActivitySessions represents concrete occurrences of activity types. For example, one weekly meeting, one FR call, one IT workshop, or one training session is an activity session. 107 108 * '''Candidate keys:''' as_id is chosen as the primary key because it keeps references to a concrete session simple. 109 * '''Attributes:''' 110 * as_id: numeric identifier, required, unique. 111 * as_start_time: timestamp, required, valid future or past timestamp depending on whether the session is planned or completed. 107 112 108 113 ==== !EventTypes ==== … … 110 115 !EventTypes represents abstract event categories, such as Job Fair, BEST Course in Summer, Motivational Weekend, beBESTIE, BOMBA, Hackathon, BEST Skopje Birthday, or other event types. It is modeled separately from event editions because the same event type can be organized multiple times over different years or editions. 111 116 112 * '''Candidate keys:''' et_name is chosen as the primary key because event type names are controlled and unique. 113 * '''Attributes:''' 117 * '''Candidate keys:''' et_id and et_name. et_id is chosen as the primary key because event type names are text labels. et_name is unique. 118 * '''Attributes:''' 119 * et_id: numeric identifier, required, unique. 114 120 * et_name: text, required, unique. 115 121 * et_description: text, required, explanation of the event type. … … 117 123 ==== !EventEditions ==== 118 124 119 !EventEditions represents one concrete edition of an event type, such as Job Fair 2026 or BEST Course in Summer 2026. It is modeled as a weak entity dependent on !EventTypes because an edition exists as an edition of an abstract event type, and the edition is identified in context by its event type, title, and start date.120 121 * '''Candidate keys:''' the chosen primary key is the composite key et_name + title + start, where et_name comes from !EventTypes and start and title are the partial keys.122 * '''Attributes:''' 123 * start: date/datetime, required, valid event start date/time.124 * e nd: date/datetime, required, must be greater than or equal to start.125 * title: text, required, title of the event edition.126 * locations: multivalued text, required because the event has at least one known location; each value is a room/place/online location.125 !EventEditions represents one concrete edition of an event type, such as Job Fair 2026 or BEST Course in Summer 2026. 126 127 * '''Candidate keys:''' ee_id is chosen as the primary key because titles and start times can change or repeat. 128 * '''Attributes:''' 129 * ee_id: numeric identifier, required, unique. 130 * ee_start_time: timestamp, required, valid event start time. 131 * ee_end_time: timestamp, required, must be greater than or equal to ee_start_time. 132 * ee_title: text, required, title of the event edition. 127 133 128 134 ==== !EventSessionTypes ==== 129 135 130 !EventSessionTypes represents abstract types of sessions inside event editions, such as official opening, company stands, official closing, lecture timeslot, coffee break, city rally, or social activity. It is modeled separately because many event sessions across different events can be of the same type and may require a typical number of volunteers. 131 132 * '''Candidate keys:''' est_name is chosen as the primary key because event session type names are controlled and unique. 133 * '''Attributes:''' 136 !EventSessionTypes represents abstract types of sessions inside event editions, such as official opening, company stands, official closing, lecture timeslot, coffee break, city rally, or social activity. It is modeled separately because many event sessions across different events can be of the same type. 137 138 * '''Candidate keys:''' est_id and est_name. est_id is chosen as the primary key because event session type names are text labels. est_name is unique. 139 * '''Attributes:''' 140 * est_id: numeric identifier, required, unique. 134 141 * est_name: text, required, unique. 135 142 * est_description: text, required, explanation of the session type. 136 * needed_no_volunteers: numeric, required, non-negative integer representing the usual needed number of volunteers.137 143 138 144 ==== !EventSessions ==== 139 145 140 !EventSessions represents concrete sessions within an event edition, such as one official opening, one company stand period, one coffee break, or one lecture slot. It is modeled as a weak entity dependent on !EventEditions and !EventSessionTypes, because an event session exists only as part of a specific event edition and it is an instance of an event session type.141 142 * '''Candidate keys:''' the chosen primary key is the composite key et_name + title + start + est_name + es_start_time + location.143 * '''Attributes:''' 144 * es_ start_time: datetime, required, valid timestamp within or near the event edition period.145 * location: text, required, room/place/online location.146 !EventSessions represents concrete sessions within an event edition, such as one official opening, one company stand period, one coffee break, or one lecture slot. It is modeled as a weak entity dependent on !EventEditions, because an event session exists only as part of a specific event edition. 147 148 * '''Candidate keys:''' the chosen primary key is the event edition key + es_no, where es_no is the partial key inside one event edition. 149 * '''Attributes:''' 150 * es_no: numeric, required, unique inside one event edition. 151 * es_start_time: timestamp, required, valid timestamp within or near the event edition period. 146 152 * es_title: text, required, title of the event session. 147 148 ==== !CoreTeamFunctions ==== 149 150 !CoreTeamFunctions represents available organizing-team functions for a specific event edition, such as Main Organiser, PR, FR, Logistics, Design, IT, HR, or another event-specific function. It is modeled as a weak entity dependent on !EventEditions because available functions are defined per event edition and may differ between event editions. 151 152 * '''Candidate keys:''' the chosen primary key is the composite key !EventEditions key + function_name. 153 * '''Attributes:''' 154 * function_name: text, required, function name unique within the same event edition. 153 * needed_no_volunteers: numeric, required, non-negative integer. 154 155 ==== !EventFunctions ==== 156 157 !EventFunctions represents available organizing functions for a specific event edition, such as Main Organiser, PR, FR, Logistics, Design, IT, HR, or another event-specific function. It is modeled as a weak entity dependent on !EventEditions because available functions are defined per event edition and may differ between event editions. 158 159 * '''Candidate keys:''' the chosen primary key is the event edition key + ef_no, where ef_no is the partial key inside one event edition. 160 * '''Attributes:''' 161 * ef_no: numeric, required, unique inside one event edition. 162 * ef_name: text, required. 155 163 156 164 ==== Applications ==== 157 165 158 Applications represents applications submitted by students, with motivation letters, for BEST Skopje processes such as applying for a core teamfunction, applying for participation connected to an event edition, applying to become a young member through BOMBA, or applying to become a mentor. It is modeled as a separate entity because applications have their own status and content and must be connected both to the applicant and to the event/function context.159 160 * '''Candidate keys:''' application_id is chosen as the primary key because one student can submit multiple applications over time and natural combinations would be less stable. 166 Applications represents applications submitted by students, with motivation letters, for BEST Skopje processes such as applying for an event function, applying for participation connected to an event edition, applying to become a young member through BOMBA, or applying to become a mentor. It is modeled as a separate entity because applications have their own status and content and must be connected both to the applicant and to the event/function context. 167 168 * '''Candidate keys:''' application_id is chosen as the primary key because one student can submit multiple applications over time and natural combinations would be less stable. 161 169 * '''Attributes:''' 162 170 * application_id: numeric identifier, required, unique. 163 171 * motivational_letter: long text, required. 164 * application_type: text, required, controlled value such as core teamfunction, event participation, BOMBA young member, or mentor application.172 * application_type: text, required, controlled value such as event function, event participation, BOMBA young member, or mentor application. 165 173 * application_status: text, required, controlled value such as submitted, accepted, rejected, or withdrawn. 166 174 … … 181 189 This specialization represents that every member is also a student, while not every student in the system must be a member. It is needed because external students can participate or apply for some activities/events, while members have additional BEST Skopje membership history, responsibilities, and roles. 182 190 183 * '''Candidate keys:''' inherited from the supertype.184 * '''Attributes:''' no relationship attributes.185 186 191 ==== Members Membership-Type Specialization ==== 187 192 188 193 This disjoint specialization separates Members into Observers, !YoungMembers, !FullMembers, and Alumni. It is needed to show the main membership stadiums clearly in the conceptual ER model. The historical periods of these stages are still stored through has_stage. 189 194 190 * '''Candidate keys:''' inherited from the supertype.191 * '''Attributes:''' no relationship attributes.192 193 195 ==== !OrganizationalFunctions Board/!NonBoard Specialization ==== 194 196 195 197 This disjoint specialization separates organizational functions into Board and !NonBoard roles. It is needed because Board membership is treated as a function/role rather than as a membership stage, but the model still needs to distinguish Board functions from other coordinator functions. 196 198 197 * '''Candidate keys:''' inherited from the supertype.198 * '''Attributes:''' no relationship attributes.199 200 199 ==== applies_with ==== 201 200 202 201 applies_with connects Students to Applications. It represents the fact that each application is submitted by exactly one student, while one student may submit many applications. It is needed to know who wrote the motivation letter and whose application status is being tracked. 203 202 204 * '''Candidate keys:''' it is stored as a foreign key from Applications to Students.205 * '''Attributes:''' no relationship attributes.206 207 203 ==== for_function ==== 208 204 209 for_function connects Applications to !CoreTeamFunctions. It represents applications that target a specific available core team function for an event edition. It is needed so that an accepted application can imply that the student became part of the core team in that function. 210 211 * '''Candidate keys:''' application_id is sufficient for this relationship since each function application targets at most one core team function. 212 * '''Attributes:''' no relationship attributes. 205 for_function connects Applications to !EventFunctions. It represents applications that target a specific available event function for an event edition. It is needed so that an accepted application can imply that the student became part of the event organization in that function. 213 206 214 207 ==== for_participation ==== … … 216 209 for_participation connects Applications to !EventEditions. It represents applications for participation in an !EventEdition, such as participant of a Hackathon, as well as applications from full members to become a mentor and observers to become a young member in BOMBA. 217 210 218 * '''Candidate keys:''' application_id is sufficient because each application targets one event edition.219 * '''Attributes:''' no relationship attributes.220 221 211 ==== available_for ==== 222 212 223 available_for connects !CoreTeamFunctions to !EventEditions. It is the identifying relationship that states which functions are available for a specific event edition. It is needed because the same function name can appear in many event editions, but the available role belongs to one concrete edition. 224 225 * '''Candidate keys:''' the relationship contributes the !EventEditions key to the weak entity key of !CoreTeamFunctions. 226 * '''Attributes:''' no relationship attributes. 213 available_for connects !EventFunctions to !EventEditions. It is the identifying relationship that states which functions are available for a specific event edition. It is needed because the same function name can appear in many event editions, but the available role belongs to one concrete edition. 214 215 * '''Candidate keys:''' the relationship identifies !EventFunctions through event edition key + ef_no. 227 216 228 217 ==== edition_of ==== … … 230 219 edition_of connects !EventEditions to !EventTypes. It represents that each concrete event edition is an edition of exactly one abstract event type. It is needed to distinguish event categories from concrete yearly/dated editions. 231 220 232 * '''Candidate keys:''' the relationship contributes the !EventTypes key to the weak entity key of !EventEditions.233 * '''Attributes:''' no relationship attributes.234 235 221 ==== part_of ==== 236 222 237 223 part_of connects !EventSessions to !EventEditions. It represents that every event session belongs to one event edition, and an event edition is composed of event sessions. It is modeled as identifying because event sessions do not exist independently of the event edition they are part of. 238 224 239 * '''Candidate keys:''' the relationship contributes the event edition key to the weak entity key of !EventSessions. 240 * '''Attributes:''' no relationship attributes. 225 * '''Candidate keys:''' the relationship identifies !EventSessions through event edition key + es_no. 241 226 242 227 ==== session_inst_of ==== … … 244 229 session_inst_of connects !EventSessions to !EventSessionTypes. It represents that a concrete event session is an instance of an abstract event session type, such as official opening or coffee break. It is needed so that sessions can be categorized consistently without duplicating type descriptions. 245 230 246 * '''Candidate keys:''' the relationship contributes the !EventSessionTypes key to the weak entity key of !EventSessions.247 * '''Attributes:''' no relationship attributes.248 249 231 ==== instance_of ==== 250 232 251 instance_of connects !ActivitySessions to !ActivityTypes. It represents that a concrete activity session is an instance of an abstract activity type, such as a weekly meeting, working group, FR call, training, or party. It is modeled as identifying because an activity session is defined through its type, start time, and location. 252 253 * '''Candidate keys:''' the relationship contributes !ActivityTypes key to the weak entity key of !ActivitySessions. 254 * '''Attributes:''' no relationship attributes. 233 instance_of connects !ActivitySessions to !ActivityTypes. It represents that a concrete activity session is an instance of an abstract activity type, such as a weekly meeting, working group, FR call, training, or party. 255 234 256 235 ==== related_to ==== 257 236 258 related_to connects !ActivitySessions to !EventEditions. It represents activity sessions that are connected to a specific event edition, such as BEST Course in Summer meetings, FR calls for a Hackathon, or working sessions for an event. It is optional because many activity sessions, such as regular weekly meetings, may not be related to a specific event edition.237 related_to connects !ActivitySessions to !EventEditions. It represents activity sessions that are connected to a specific event edition, such as BEST Course in Summer meetings, FR calls for a specific event, or working sessions for an event. It is optional because many activity sessions, such as regular weekly meetings, may not be related to a specific event edition. 259 238 260 239 * '''Candidate keys:''' the natural key is the activity session key because each activity session is related to at most one event edition in the current model. 261 * '''Attributes:''' no relationship attributes. 240 241 ==== takes_place_at ==== 242 243 takes_place_at connects !ActivitySessions to Locations. It represents the location where a concrete activity session is held. 244 245 ==== hosted_at ==== 246 247 hosted_at connects !EventEditions to Locations. It represents the one or more locations connected to an event edition. 248 249 * '''Candidate keys:''' event edition key + location key. 250 251 ==== held_at ==== 252 253 held_at connects !EventSessions to Locations. It represents the location where a concrete event session is held. 262 254 263 255 ==== participation ==== … … 265 257 participation connects Students to !ActivitySessions. It represents RSVP and attendance checking for activity sessions, such as meetings, workshops, trainings, FR calls, parties, or other internal activities. It is needed because students or members can say they are going and the organization can later record whether they attended. 266 258 267 * '''Candidate keys:''' index + activity session key is chosen as the primary key because one student should have at most one participation record for the same activity session.268 * '''Attributes:''' 269 * rsvp_status: text, required, controlled value such as going, not going, maybe, or de fault = no response.270 * rsvp_at: datetime, optional until an RSVP is submitted; required when an RSVP is recorded.259 * '''Candidate keys:''' student_index + activity session key is chosen as the primary key because one student should have at most one participation record for the same activity session. 260 * '''Attributes:''' 261 * rsvp_status: text, required, controlled value such as going, not going, maybe, or deault = no response. 262 * rsvp_at: timestamp, optional until an RSVP is submitted; required when an RSVP is recorded. 271 263 * attendance_status: text, required when attendance is checked, controlled value such as present, absent, excused, late, online, left early or not checked. 272 264 … … 275 267 announces_absence connects Members to !ActivitySessions. It represents members announcing that they will be absent from an activity session, with a reason and time of announcement. It is needed for processes where absence from mandatory or important activities should be communicated before the session. 276 268 277 * '''Candidate keys:''' member index + activity session key is the natural primary key becausea member can have only one active absence announcement per session.269 * '''Candidate keys:''' member student_index + activity session key is the natural primary key if a member can have only one active absence announcement per session. 278 270 * '''Attributes:''' 279 271 * reason: text, required, explanation of the absence. 280 * announced_at: datetime, required, timestamp when the absence was announced.272 * announced_at: timestamp, required, timestamp when the absence was announced. 281 273 282 274 ==== responsible_for ==== 283 275 284 responsible_for connects Members to !ActivitySessions. It represents members responsible for organizing or holding an activity session, such as the President holding weekly meetings, HR coordinating training sessions, or event organizers/core team members coordinating event-related activity sessions. 285 286 * '''Candidate keys:''' member index + activity session key is the natural primary key because the same member should not be linked twice as responsible for the same session. 287 * '''Attributes:''' no relationship attributes. 276 responsible_for connects Members to !ActivitySessions. It represents members responsible for organizing or holding an activity session, such as the President holding weekly meetings, HR coordinating training sessions, or event organizers coordinating event-related activity sessions. 277 278 * '''Candidate keys:''' member student_index + activity session key is the natural primary key because the same member should not be linked twice as responsible for the same session. 288 279 289 280 ==== volunteers ==== 290 281 291 volunteers connects Members to !EventSessions. It represents members volunteering for concrete event sessions, such as helping at company stands, coffee breaks, official openings, social activities, or other event-session tasks. It is modeled separately from core teamapplications because volunteering for a session is operational help, not necessarily an organizing-team function.292 293 * '''Candidate keys:''' member index + event session key + volunteer_role is the primary key since one member can volunteer in multiple roles for the samesession.294 * '''Attributes:''' 295 * volunteer_role: text, required , description or controlled value of the volunteer task/role.282 volunteers connects Members to !EventSessions. It represents members volunteering for concrete event sessions, such as helping at company stands, coffee breaks, official openings, social activities, or other event-session tasks. It is modeled separately from event function applications because volunteering for a session is operational help, not necessarily an organizing-team function. 283 284 * '''Candidate keys:''' member student_index + event session key is chosen because one member is stored once for the same event session. 285 * '''Attributes:''' 286 * volunteer_role: text, required. 296 287 297 288 ==== has_stage ==== … … 299 290 has_stage connects Members to !MembershipStages. It stores membership history: which membership stage a member had and during what period. It is needed even though member subtypes exist, because subtypes show the conceptual categories while this relationship records time periods and transitions. 300 291 301 * '''Candidate keys:''' member index + ms_name+ valid_from is chosen because a member can potentially enter the same stage more than once over time.292 * '''Candidate keys:''' member student_index + ms_id + valid_from is chosen because a member can potentially enter the same stage more than once over time. 302 293 * '''Attributes:''' 303 294 * valid_from: date, required, start date of the membership stage. 304 * valid_to: date, optional for the current active stage; When present, must be greater than or equal to valid_from.295 * valid_to: date, optional for the current active stage; when present, must be greater than or equal to valid_from. 305 296 306 297 ==== mentorship ==== 307 298 308 mentorship connects !FullMembers to !YoungMembers. It represents that a young member must have a mentor who is a full member. 309 310 * '''Candidate keys:''' the young member key is sufficient since each young member has exactly one mentor forever. 311 * '''Attributes:''' no relationship attributes. 312 313 ==== is ==== 314 315 is connects !FullMembers to !OrganizationalFunctions. It represents a full member holding an organizational function during a mandate. It is needed because Board membership and coordinator responsibilities are roles held by full members, not separate membership stages. 316 317 * '''Candidate keys:''' full member index + of_title + mandate is chosen because the same full member can hold different functions and the same function can be held by different full members in different mandates. 318 * '''Attributes:''' 319 * mandate: text or date-range label, required, controlled format such as 2025/2026. 299 mentorship connects !FullMembers to !YoungMembers. It represents that a young member must have a mentor who is a full member. 300 301 ==== holds_function ==== 302 303 holds_function connects !FullMembers to !OrganizationalFunctions. It represents a full member holding an organizational function during a mandate. It is needed because Board membership and coordinator responsibilities are roles held by full members, not separate membership stages. 304 305 * '''Candidate keys:''' full member student_index + of_id + mandate_year is chosen because the same full member can hold different functions and the same function can be held by different full members in different mandates. 306 * '''Attributes:''' 307 * mandate_year: numeric, required, year of the organizational function mandate. 320 308 321 309 ==== cooperation ==== … … 323 311 cooperation connects Companies to !EventEditions. It represents cooperation between a company and a specific event edition, such as sponsorship, partnership, Job Fair participation, challenge provider, or similar cooperation. It is intentionally simple because detailed company contacts and communications are outside this project scope. 324 312 325 * '''Candidate keys:''' c_id + event edition key + cooperation_type since one company can cooperate with the same event edition in multiple ways.313 * '''Candidate keys:''' c_id + event edition key is chosen because one company is stored once per event edition in this model. 326 314 * '''Attributes:''' 327 315 * cooperation_type: text, required, controlled value such as sponsor, partner, participant, challenge provider, or supporter. … … 338 326 ||v08||Changed the weak entity keys of !EventSessions, !EventEditions and !ActivitySessions to account for edge cases where two sessions or editions could otherwise have the same identifying values and need location/title/start time to distinguish them.|| 339 327 ||v09||Removed "required_attendance" relationship after realising it is redundant.|| 328 ||v10||Changed string primary keys to numeric identifiers where needed. Renamed the student key from index to student_index. Added Locations as an entity. Changed !ActivitySessions, !EventEditions, !EventSessionTypes, !EventSessions and !EventFunctions to use numeric identifiers/partial numeric identifiers. Changed !EventSessions, !EventEditions and !ActivitySessions to not be weak entities. Renamed !CoreTeamFunctions to !EventFunctions and renamed the relationship between !FullMembers and !OrganizationalFunctions from is to holds_function. Made some relationships to be mandatory based on logic.|| 340 329 341 330 == AI Use ==
