Skip to Content
📘 ClubUp v0.1 — koncepčný návrh. Implementácia ešte nezačala.
Doménový modelCourse (Kurz)

Course (Kurz)

Kurz — najvyššia jednotka vzdelávania v ClubUp.

Účel

Course reprezentuje konkrétny vzdelávací produkt, ktorý sa dá kúpiť, absolvovať a získať z neho finálny certifikát (od Žilinskej univerzity). Príklady:

  • „Športový manažment pre silnejšie kluby” (prvý kurz, štart Fáza 1)
  • Plánované ďalšie kurzy: „Marketing pre menšie kluby”, „Financovanie športovej organizácie”

Kurz je usporiadaný do hierarchie:

Course └── Level (Úroveň, povinná sekvencia) └── Topic (Téma, organizačný kontajner bez testu) └── Module (Modul, hodnotiaca jednotka) └── Part (Časť, jednotka obsahu)

Schéma

PoleTypRequiredPopis
_idObjectIdPrimárny kľúč
slugstring (unique)URL-friendly identifikátor (sportovy-manazment)
titlestringNázov kurzu (zobrazovaný)
subtitlestringSekundárny názov / tagline
descriptionstring (Markdown)Detailný popis pre marketing stránku kurzu
shortDescriptionstring1–2 vety pre kartu v katalógu
coverImageUrlstring (URL)Hlavný obrázok kurzu (na karte aj v hero kurzu)
priceCentsnumber (int)Cena v centoch (12000 = 120,00 €)
currencystringISO 4217, default EUR
vatRatenumberDPH sadzba (0.20 pre 20%)
vatIncludedbooleanČi je priceCents vrátane DPH
targetAudiencestring[]executive_director, manager, founder, secretary
languagestringISO 639-1 (sk)
durationHoursnumberOdhadovaný čas absolvovania celého kurzu (samoštúdium + webináre)
levelsObjectId[]Referencie na Level v poradí (1..N, povinné poradie)
courseTestIdObjectIdVoliteľný záverečný test celého kurzu. Ak je definovaný, určuje vydanie final certifikátu.
courseTestRequiredbooleantrue → kurz nie je dokončený bez prejdenia Course-testu. Default true, ak courseTestId existuje.
instructorsstring[]sportup_person_id lektorov
instructorProfilesInstructorProfile[]Snapshot mena, fota, bio v čase publikácie
accreditationAccreditationÚdaje o akreditovanom partnerovi (Žilinská univerzita) — povinné pre vydávanie final certifikátu
stateenumdraft, published, archived
versionnumberVerzia (po publikovaní immutable, nová verzia = nový dokument)
previousVersionIdObjectIdOdkaz na predošlú verziu, ak existuje
publishedAtDateKedy bol publikovaný
archivedAtDateKedy bol archivovaný
enrollmentLimitnumberMax. počet aktívnych enrollmentov (null = unlimited)
enrollmentDeadlineDatePosledný možný dátum kúpy
seoTitlestring<title> na verejnej stránke
seoDescriptionstring<meta description>
ogImageUrlstringOG image pre sociálne siete
tagsstring[]Pre vyhľadávanie a filtrovanie
createdAtDate
updatedAtDate
createdBystringsportup_person_id autora draftu
publishedBystringsportup_person_id osoby, ktorá publikovala

Sub-typy

type InstructorProfile = { sportupPersonId: string; displayName: string; title?: string; // "PhD.", "Mgr." bio?: string; // krátky bio (Markdown) avatarUrl?: string; affiliation?: string; // "FRI ŽU" }; type Accreditation = { partnerOrgId: string; // sportup_org_id of ŽU partnerName: string; // "Žilinská univerzita v Žiline, FRI" certificateType: string; // "Osvedčenie o absolvovaní vzdelávacieho programu" accreditationNumber?: string; // číslo akreditácie u MŠVVaŠ SR };

Indexy

db.courses.createIndex({ slug: 1 }, { unique: true }); db.courses.createIndex({ state: 1, publishedAt: -1 }); db.courses.createIndex({ tags: 1 }); db.courses.createIndex({ 'instructorProfiles.sportupPersonId': 1 });

Životný cyklus

Pravidlá

  • draftpublished je možné iba ak:
    • kurz má aspoň 1 Level
    • každý Level má aspoň 1 Topic
    • každá Topic má presne 1 Module
    • každý Module má aspoň 1 Part
    • aspoň jedna Part v každom Module je requiredForCompletion: true
    • cena je nastavená
    • accreditation je vyplnený
    • ak courseTestId existuje, je validný (placement = ‘course’)
  • publishedarchived je možné kedykoľvek; existujúce enrollmenty pokračujú normálne, len sa kurz nedá kupovať
  • archivedpublished je možné, pokiaľ ešte neuplynula enrollmentDeadline
  • Mazanie — kurz sa nedá zmazať, ak má aspoň jeden enrollment. Iba archivovať. Toto je kvôli auditu a finančným záznamom.

Versioning

Po publikovaní je dokument Course (a všetky jeho Level, Topic, Module, Part, Test) immutable v zmysle UI editácie. Ak content_manager chce zmeniť obsah:

  1. Vytvorí novú verziu cez „Vytvoriť novú verziu” → vznikne nový Course dokument s version: previous.version + 1, previousVersionId: previous._id, state: 'draft'
  2. Pri vzniku novej verzie sa klonujú aj všetky pod-entity (Levels, Topics, Modules, Parts, Tests) s novými _id, ale s rovnakou štruktúrou — content_manager ich potom môže upravovať
  3. Editácia, publikácia
  4. Stará verzia ostáva pre už zapísaných študentov (Enrollment.courseVersionId)
  5. Nové enrollmenty idú do novej verzie

Dôvod: študent kúpil konkrétny obsah, musí ho dostať. Aj kvôli akreditácii — Žilinská univerzita certifikuje konkrétnu verziu kurzu.

Dokončenie kurzu (final certifikát)

Kurz je completed, keď:

  1. Všetky Levels sú completed (každý Level má dokončené všetky moduly + Level-test, ak je required), A
  2. Ak courseTestId existuje a courseTestRequired: true, študent prešiel Course-test

Po completed sa spúšťa proces vydania final certifikátu (viď certificate.md — flow s Žilinskou univerzitou).

Príklad dokumentu

{ "_id": "ObjectId('66e1f8a0123456789abcdef0')", "slug": "sportovy-manazment", "title": "Športový manažment pre silnejšie kluby", "subtitle": "Komplexné vzdelávanie pre výkonných riaditeľov", "shortDescription": "10 tém, 40 modulov, 4 úrovne — od základov po stratégiu.", "description": "## O kurze\n\nKomplexné vzdelávanie pre ľudí, ktorí riadia športové kluby...", "coverImageUrl": "https://cdn.clubup.sk/courses/sportovy-manazment/cover.webp", "priceCents": 49000, "currency": "EUR", "vatRate": 0.20, "vatIncluded": true, "targetAudience": ["executive_director", "founder", "secretary"], "language": "sk", "durationHours": 40, "levels": [ "ObjectId('level_1_zaklady')", "ObjectId('level_2_pokrocily')", "ObjectId('level_3_specialista')", "ObjectId('level_4_strateg')" ], "courseTestId": null, "courseTestRequired": false, "instructors": ["sportup_person_id_1", "sportup_person_id_2"], "instructorProfiles": [ { "sportupPersonId": "sportup_person_id_1", "displayName": "Doc. Ing. Ján Príklad, PhD.", "bio": "Pôsobí na Fakulte riadenia a informatiky ŽU...", "affiliation": "FRI ŽU" } ], "accreditation": { "partnerOrgId": "sportup_org_id_zu", "partnerName": "Žilinská univerzita v Žiline, Fakulta riadenia a informatiky", "certificateType": "Osvedčenie o absolvovaní vzdelávacieho programu", "accreditationNumber": "123/2026" }, "state": "published", "version": 1, "publishedAt": "2026-09-01T08:00:00Z", "enrollmentLimit": null, "enrollmentDeadline": null, "seoTitle": "Športový manažment pre silnejšie kluby — ClubUp", "seoDescription": "Komplexné vzdelávanie pre výkonných riaditeľov...", "tags": ["manazment", "kluby", "akreditovany-kurz"], "createdAt": "2026-08-15T10:00:00Z", "updatedAt": "2026-09-01T08:00:00Z", "createdBy": "sportup_person_id_creator", "publishedBy": "sportup_person_id_admin" }

Pozn.: Tento kurz nemá courseTestId — finálny certifikát sa vydá po dokončení posledného Levelu (level_4_strateg) vrátane jeho Level-testu.

API operácie

OperáciaEndpointRoly
List publishedGET /api/coursespublic
Detail (slug)GET /api/courses/:slugpublic
Detail (admin, vrátane drafts)GET /api/admin/courses/:idcontent_manager+
Create draftPOST /api/admin/coursescontent_manager+
Update draftPATCH /api/admin/courses/:idcontent_manager+
PublishPOST /api/admin/courses/:id/publishadmin
ArchivePOST /api/admin/courses/:id/archiveadmin
Create new versionPOST /api/admin/courses/:id/new-versioncontent_manager+

Detaily v ../api/courses.md.