Backend: Adding new BTC školovanje
Last modified with commit 374306c on
by Aljaž.
Backend task for creating a BTC školovanje (POST /btc-trainings) – check the API spec and DB structure, set up the btc-trainings permissions, tables and lookups, create the 4 fixed modules, implement, and verify against the spec.
Docs: Adding new BTC školovanje
Spec: POST /btc-trainings (createBtcTraining), BtcTrainingNewRequest, BtcTraining, BtcStatus in api-docs/openapi.yaml
DB: BtcTrainings, BtcTrainingModules, BtcTrainingCandidates in api/database/create_schema.sql
This is the first BTC školovanje endpoint, so it also includes the shared setup for the školovanje sub-area: permissions, tables, the status helper and the Partner lookup.
1. Double check API spec and DB structure
Every docs field is in
BtcTrainingNewRequest, with the right required/optional setting: Marka (multiselect →brandCodes), Naziv školovanja (name), Termini po modulima (modules,startDate/endDateoptional), and candidates: Ime i prezime (required), E-mail (optional), Partner (required,partnerId), Marka (kandidat) (required,brandCode).Limits: 1–20 candidates (
minItems/maxItems),modulesexactly 4 withmoduleNumber1–4, each once. Check the docs and the spec agree.Date validation: the spec and the
CK_BtcTrainingModules_Datesconstraint check end ≥ start inside one module.Marka (kandidat): the docs ask whether its options are limited to the brands selected under Osnovni podaci. If yes, the backend must validate
brandCode∈brandCodes(→ 400). Decide and update the spec.E-mail format: the request has no
format: email. Decide whether an invalid e-mail is rejected (→ 400) or stored as free text.Default structure: the docs say 4 modules (each with Dan 1 / Dan 2), a Rezultati feedback forme page and a Potpisi page are created. In the schema this is only the 4 BtcTrainingModules rows. Attendance, feedback values and files start empty. The “feedback form” of each module is not part of the app. Confirm nothing else must be created.
Each DB column has a request field or a value set by the server (
CreatedBy,CreatedAt). Use the sameCreatedByvalue (user id or display name) as Assessments.Is
201+BtcTrainingenough for the next step (back to the list with a toast)?Roles and permissions: the spec uses
btc-trainings.edithere andbtc-trainings.accesson the read endpoints. Neither exists inapi/Authorization/Permissions.cs. Per the BTC roles comment, only the Trainer role has access to BTC školovanje (Assessment evaluators and BTC evaluators don’t). Confirm, and confirm whether Admin also gets them.Brand restriction:
PermissionService.GetLimitedBrandCodesrestricts some users to brands. Decide whether this applies to BTC školovanje (the docs say Trainers see everything, so recommended: no).DB:
BrandCodes VARCHAR(6)vs^[SACVUL]{1,6}$;BtcTrainingCandidates.BrandCode CHAR(1)with the brandCHECK;UQ_BtcTrainingModules (TrainingId, ModuleNumber)withModuleNumber1–4 (at most 4 modules, each once);UQ_BtcTrainingCandidates_Slotcaps candidates at 20 (the minimum is checked in code;Slotis not the display order, that’sCreatedAt).Partner lookup: Partner is a dropdown. Today
partnerIdis free text and there is no partner source inapi/. Use the same decision as Backend: Adding new assessment and reuse its endpoint.
2. Implementation
- Roles and permissions: add
btc-trainings.accessandbtc-trainings.edittoPermissions.csand grant both to Trainer (and Admin, if confirmed). The Trainer role is added toRoleCode.csby the assessments task. If that hasn’t been done yet, add it here (code,GetRolescatalog). Add the two names to thePermissionNameenum check. - DB: apply the
-- BTC ŠKOLOVANJE --section ofcreate_schema.sql(plus a migration script for existing environments, if used). Add the status helper fromBtcStatus: today’s date in Europe/Zagreb (TimeZoneInfo“Europe/Zagreb”, as inEventInviteesRepository.Documents.cs);pastwhen Modul 4EndDate< today; otherwiseupcomingwhen Modul 1StartDateis null or > today; otherwiseactive. Write it so it can also be used as a SQL expression (the list filters and sorts by status). - Lookups: Partner dropdown from the shared partner source.
- Function + repository. Insert BtcTrainings, the 4 BtcTrainingModules rows (dates from the
request) and the candidates in one transaction (several writes). Candidates get
Slot1…n in request order. - Validation → 400 (
validation_error): required fields;brandCodespattern with no duplicate letters; 1–20 candidates; exactly modules 1–4; end ≥ start per module; lengths (name,fullName,email255,partnerId50); plus the rules decided in step 1. - Requires
btc-trainings.edit→ 403. Response 201 withBtcTraining(calculatedstatus,module1StartDate,module4EndDate,candidatesCount).
3. Verify implementation against spec
- Route, method, request and response shapes match
createBtcTraining. - 400 / 401 / 403 / 500 cases can be produced; no undocumented status codes.
- Assessment evaluator / BTC evaluator token → 403. 21 candidates → 400. Three modules, or module 2 twice → 400. Modul 1 end before start → 400.
- Status of the created školovanje: no dates →
upcoming; Modul 1 start today and no Modul 4 end →active; Modul 4 end yesterday →past. -
GET /me/permissionsfor a Trainer includesbtc-trainings.accessandbtc-trainings.edit. Permission names inPermissions.csmatch thePermissionNameenum.
Done when
A trainer can create a BTC školovanje, which then shows on the list and opens on the detail page with 4 empty modules.
validation_error; also decide what happens when a module in between has no dates) and the rule goes into theBtcTrainingNewRequest/createBtcTrainingdescription. See the comment on Adding new BTC školovanje.