feat(timetable): publish a generated scenario as draft lessons for its window - #798
Merged
Merged
Conversation
…er day and room use
…oft, on the week grid
…wish, in time-boxed background steps
…ike a generated one
…lue marked, differing lessons listed
…ery week of its window
…ing in the publisher
Contributor
Quality Report — ConductionNL/planninq @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| check-l10n-js | ✅ | ||||
| check-schema-l10n | ✅ | ||||
| composer | ✅ | ✅ 107/107 | |||
| npm | ✅ | ✅ 646/646 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| lockfile sync | ✅ | ||||
| PHPUnit | ❌ | ||||
| Newman | ❌ | ||||
| Playwright | ⏭️ deferred: E2E runs locally and on the promotion path only. This pull request targets development, so the suite is asked once per promotion into beta and main rather than once per push per open pull request. Run it on any branch from the Actions tab, or locally with npx playwright test. |
||||
| Hydra gates | ✅ |
Quality workflow — 2026-09-30 07:21 UTC
Download the full PDF report from the workflow artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Timetable generator, section 8: publish a generated scenario as draft lessons
Base: development (19711e0). Sits on #797 (section 7, compare), which sits on #796, #795, #794, #793 and #791. Merge in that order, or merge this PR with a merge commit to land all seven.
Change:
timetabling-generator(DECISIONS rows 17 and 21), section 8 of 9 (task 8.1). The change stays open; section 9 (docs, Newman) archives it.What the user can now do
On a generated scenario that is done, an admin presses "Publish as draft lessons". Planninq writes every placement as a draft lesson for every week of the scenario's window, with source
planninq-generatorand external reference{scenario}:{lesson}:{date}, and marks the scenario published. The existing draft review then applies unchanged: teachers see their own drafts, an admin publishes them. Drafts of an earlier scenario for the same window are replaced. When lessons of that window from the generator are already published, nothing is written and the admin reads why. A scenario taken from the current timetable is not published again.How
lib/Service/TimetableScenarioPublisher.php(design decision 7): turns each placement's period key and the grid's period times (TimetableGridService::periodTimes(), section 6) intostartsAt/endsAtper week (a two-period lesson ends at the end of its second period), removes the generator's drafts of other scenarios in the window, and upserts through the existingTimetableSessionService::upsert(idempotent by source and external reference).TimetableScenarioStore::lessonsFrom()anddeleteLesson(); the window is re-checked in PHP.POST /api/timetable/scenarios/{id}/publish-drafts(TimetableScenarioController::publishDrafts, admin:AuthorizedAdminSettingplus an admin check; 403 otherwise, 400 with the reason when refused).canPublishDrafts. 3 new strings in all 36 locales.Tests
tests/unit/Service/TimetableScenarioPublisherTest.php(4), the real store, session service and grid over an in-memory ObjectService: every week of the window gets the pattern as drafts (4 created, a two-period Maths lesson 10:10 to 11:50), every saved payload validated against the realtimetableSessionfragment (Opis), the scenario marked published (scenario "Publish a scenario as drafts"); a second scenario replaces the first one's drafts; a window with a published generator lesson is refused and nothing changes; an imported scenario is refused.tests/unit/Controller/TimetableScenarioControllerTest.php(+2): a non-admin is refused; an admin gets the counts, or 400 with the reason.tests/vitest/timetableScenarios.spec.js(+1): the button shows only for a finished generated scenario with placements.Red first: the publisher tests failed with the class missing, the controller tests on the unknown
publisherargument, the vitest case on the missing helper, and the imported-scenario case before the publisher checked the source (lane loglane17/red-s8.log).Verification
At head d1686d0 (development 19711e0 + #791 + #793 + #794 + #795 + #796 + #797 + this section):
composer check:strict1 (phpmd: a short method name and static date parsing in the publisher) then phpmd 0 on the file, phpcs, psalm, phpstan 0, PHPUnit 536 (7 skipped). npm lint, stylelint, check:l10n, check:l10n-js, check:schema-l10n, check:manifest, vitest (423 tests) and build all 0. CI-shaped Hydra gates (hydra-gates@main, full coverage, this body): ALL 82 applicable gates passed.Live check
POST /apps/planninq/api/timetable/scenarios/<id>/publish-draftsanswers 403.Inherited: the non-required Newman, PHPUnit (pgsql) and Quality Report jobs have been red on every PR since #758.
🤖 Generated with Claude Code