Cancellation was welded to the workflow: the confirmation email was a side effect of the cancel-window park, so disabling self-service cancellation also killed the confirmation email. And the refund configuration lived on the core resource type, though core must know nothing about payment.
This reworks cancellation into a self-contained core capability. A signed, order-scoped link (CancelToken) points at a core controller that verifies the link and re-checks the cancellation policy, then dispatches a claimable event. When Orchestra runs the booking, a listener claims the event and redirects the booker into the existing booking_cancel interaction, so the workflow drives the cancellation (its join, the operator refund review, and the notifications) unchanged; with no workflow, core confirms and cancels directly.
The confirmation email becomes a visible notify:confirmed workflow node, alongside notify:cancelled and notify:rejected, with a plain or a cancellable Easy Email template chosen by policy, so a non-cancellable booking never shows a dead cancel button.
Refund moves entirely into yoyaku_payment: a RefundPolicy and resolver, with the type default in yoyaku_payment third-party settings and a per-resource override base field. BookingScheduleResolver::consumingResources() is exposed as the public building block the payment refund policy aggregates over, so core stays payment-agnostic.
A fully Orchestra-free yoyaku (an instance-free core mail path) is left to follow-up issues.
Issue fork yoyaku-3612196
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
mably commentedComment #4
mably commentedComment #6
mably commented