Files
unsupervised-scheduler/docs/features/policies.md
T
thatguygriff 6225e772f8
CI / Coding Standards (pull_request) Successful in 1m0s
CI / PHPStan (pull_request) Successful in 1m4s
CI / Tests (PHP 8.1) (pull_request) Successful in 59s
CI / Tests (PHP 8.2) (pull_request) Successful in 56s
CI / Tests (PHP 8.3) (pull_request) Successful in 57s
CI / No Debug Code (pull_request) Successful in 3s
CI / Build Plugin Zip (pull_request) Has been skipped
Add Policies domain (drafting, versioning, tracked acceptance)
Implements #6: studio admins draft, version, and publish policies; the
public registration gate reads the current published version of each, and
acceptance is recorded against the exact version so a new version must be
re-accepted at the next booking.

- src/Policy/: Policy, PolicyVersion, PolicyAcceptance value objects;
  PolicyRepository, PolicyVersionRepository, AcceptanceRepository;
  PolicyService (orchestrates create/add-draft/publish across the policies
  and versions tables); PolicyEndpoint (REST); PolicyController +
  templates/admin/policies.php (Policies admin menu, manage_policies)
- us_policies, us_policy_versions, us_policy_acceptances tables in Schema
- REST: public GET /policies (current published versions); manage_policies
  for create, add version, edit draft, and publish
- Wiring in Plugin, RestRegistrar, AdminMenu

AcceptanceRepository is built now and consumed by the booking/enrolment
gate in #3/#4.

Also bump PHPStan to --memory-limit=1G in the composer lint script; the
default 128M now crashes the analysis as the codebase has grown.

Tests: tests/Unit/Policy/ (value objects, repositories, service).
composer test (90 total), cs, and PHPStan level 6 all pass.

Refs #6

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 15:00:54 -03:00

5.4 KiB

Feature: Policies

Overview

The studio admin drafts, versions, and publishes policies (e.g. cancellation, payment, code of conduct). Registrants must read and accept the current published version of every policy before they can book. Acceptance is recorded against the specific version, so when a policy is updated students must re-accept it at their next booking.

Data Model — {prefix}us_policies

Column Type Notes
id BIGINT UNSIGNED Primary key
title VARCHAR(191) Display name
slug VARCHAR(191) Unique key, e.g. cancellation
current_version_id BIGINT UNSIGNED Nullable FK → us_policy_versions.id (published)
created_at DATETIME Insertion time

Data Model — {prefix}us_policy_versions

Column Type Notes
id BIGINT UNSIGNED Primary key
policy_id BIGINT UNSIGNED FK → us_policies.id
version_number INT Increments per policy, starting at 1
body LONGTEXT The policy text (HTML/markdown)
status VARCHAR(20) draft / published / archived
published_at DATETIME When published; NULL for drafts
created_at DATETIME Insertion time

Data Model — {prefix}us_policy_acceptances

Column Type Notes
id BIGINT UNSIGNED Primary key
policy_version_id BIGINT UNSIGNED FK → us_policy_versions.id (the exact version accepted)
student_id BIGINT UNSIGNED WordPress user ID
registration_type VARCHAR(20) lesson or enrollment
registration_id BIGINT UNSIGNED FK → us_lessons.id or us_group_enrollments.id
accepted_at DATETIME Timestamp of acceptance
ip_address VARCHAR(45) IP captured at acceptance (audit trail)

Versioning & Acceptance Rules

  • Editing a published policy creates a new draft version; the old version stays published until the draft is published.
  • Publishing a draft sets it published, stamps published_at, archives the prior version, and points us_policies.current_version_id at it.
  • The registration gate requires acceptance of the current_version_id of every policy. Because acceptance is tied to policy_version_id, a newly published version is unaccepted and must be re-accepted at the student's next booking.

Admin Interface

Policies in wp-admin (manage_policies, studio admin only):

  • Create a policy; draft and edit version bodies
  • Publish a draft version; view acceptance history per version

REST API

Method Endpoint Permission
GET /wp-json/us-scheduler/v1/policies Public (current published versions)
POST /wp-json/us-scheduler/v1/policies manage_policies
POST /wp-json/us-scheduler/v1/policies/{id}/versions manage_policies
PATCH /wp-json/us-scheduler/v1/policies/{id}/versions/{vid} manage_policies
POST /wp-json/us-scheduler/v1/policies/{id}/versions/{vid}/publish manage_policies

Acceptances are not posted directly — they are written as part of POST /bookings and POST /enrollments via the accepted_policy_version_ids[] field, which must cover every policy's current version or the registration is rejected.

Implementation

  • Repositories: Unsupervised\Schedular\Policy\PolicyRepository, Unsupervised\Schedular\Policy\PolicyVersionRepository, Unsupervised\Schedular\Policy\AcceptanceRepository
  • Models: Unsupervised\Schedular\Policy\Policy, Unsupervised\Schedular\Policy\PolicyVersion, Unsupervised\Schedular\Policy\PolicyAcceptance
  • Service: Unsupervised\Schedular\Policy\PolicyService — orchestrates create / add-draft / publish across the policies and versions tables (archive prior current version, stamp published_at, repoint current_version_id)
  • Admin controller: Unsupervised\Schedular\Policy\PolicyController
  • REST endpoint: Unsupervised\Schedular\Policy\PolicyEndpoint

Tests

  • tests/Unit/Policy/PolicyValueObjectsTest.php
  • tests/Unit/Policy/PolicyRepositoryTest.php
  • tests/Unit/Policy/PolicyVersionRepositoryTest.php
  • tests/Unit/Policy/AcceptanceRepositoryTest.php
  • tests/Unit/Policy/PolicyServiceTest.php