Group class offerings now carry real dates: the add/edit form takes a
start date plus a sessions control (one-off, or weekly for N sessions;
the end date is computed as start + (N-1) weeks via
Offering::weeklyTermEnd). Dates are validated strictly (Y-m-d) and shown
in the offerings list and on the student-facing class card, including
the weekly session count.
[us_group_classes offering="<id>"] (block attribute offeringId, chosen
from a dropdown of active classes fetched from the public offerings
endpoint) restricts the page to a single class so the enrolment flow can
be embedded on a page dedicated to that class; a pinned class that is no
longer offered reports itself closed instead of falling back to the
catalog.
Offerings are now editable from the admin screen: an Edit button
prefills the shared add/edit form and saving posts usc_action=update.
Updates always preserve the original owner and currency, and non-admin
instructors can only load and update their own offerings. The form also
gains the previously missing description field and an Active toggle (the
admin-UI counterpart of the REST is_active flag) so an edit cannot wipe
data the form never collected.
Closes#59
Co-Authored-By: Claude Fable 5 <[email protected]>
The e-transfer destination is resolved at booking time (offering override ->
studio default) and frozen onto the payment, so each record keeps where the
student was directed. It can then be corrected per booking.
- StudioSettings: us_etransfer_email option + a Default e-transfer email field
on the Studio Settings page.
- Offering: etransfer_email column/field (instructor override) across VO, repo,
REST endpoint, admin controller, and form.
- Payment: etransfer_email column on the payment (frozen record) +
PaymentRepository::updateEtransferEmail; PaymentService freezes it from the
offering override or studio default at creation; booking/enrolment pass the
offering override.
- My Lessons: instructors edit the e-transfer email per pending lesson payment
(ownership-checked).
- Payments queue: studio admin can correct the email at confirmation (for when
a student sends it to the wrong place).
- Docs updated.
Tests: Payment/Offering rows + PaymentService freezing. composer test (148),
cs, and PHPStan level 6 all pass.
Refs #7
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Availability (#2):
- us_availability gains offering_id, duration_minutes (default 60), and
recurrence_group; AvailabilitySlot carries the new fields.
- AvailabilityRepository::createWeeklySeries() generates N weekly rows
sharing a recurrence_group; findAvailable() filters by offering and
duration. Date math uses DateTimeImmutable::modify() (the no-debug CI
regex `dd\(` matches `->add(`).
- REST GET filters by offering_id/duration_minutes; POST accepts
duration_minutes, offering_id, recurrence (single|weekly) + weeks.
- Admin form adds duration, an offering picker, and one-off/weekly options
(OfferingRepository wired into AvailabilityController).
- booking.js renders an agenda calendar (slots grouped by day, with
duration). The richer booking UX lands with the booking-flow work.
Offering price in dollars:
- Switch us_offerings.price_cents (INT) to price DECIMAL(10,2); Offering
uses float $price. Admin form and REST take dollars.
- Fix a pre-existing misalignment in the Offering insert/update $wpdb
format arrays (billing_mode/capacity/is_active were mapped to the wrong
specifiers, which would corrupt values) via a single COLUMN_FORMATS list.
Also bump PHPStan to --memory-limit=1G in the lint script; 128M now
crashes analysis as the codebase has grown.
Refs #2
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Implements the offerings catalog (#1): private-lesson types and group
classes carrying pricing, billing mode (one_time/full_term), duration,
capacity, and term details. Adds the src/Offering/ domain (value object,
repository, REST endpoint, admin controller + template), the us_offerings
table, and an Offerings admin page.
Also lands the capability slice of #9: registers the us_studio_admin role
and the new capability strings (manage_instructors, manage_offerings,
manage_questions, manage_policies, manage_billing, view_all_payments,
view_own_payments, export_payments) so offering management gates correctly.
Tests: tests/Unit/Offering/ (value object + repository) and a studio-admin
case in RoleManagerTest. composer test, cs, and PHPStan level 6 all pass.
Refs #1#9
Co-Authored-By: Claude Opus 4.8 <[email protected]>