Problem/Motivation

CancelLinkBuilder describes itself as "the one place that mints the signed cancel URL, so every surface that offers cancellation (the confirmation screen, the confirmation email, an account view) asks the same question and gets the same link". Only the mail ever asks.

A booker reading their confirmation has no way to cancel, although the cancellation window is open beside them: the workflow forks into n_cancel_window and n_await_guarantee together, and the booking_cancel interaction only renders once the booker arrives from the mailed link.

Proposed resolution

Add [yoyaku-order:cancel-url], minted by the same builder, so a message can carry the link from config the way [yoyaku-order:bookings] already carries the booking list. No new plugin and no new render path, and a page and a mail cannot drift apart about whether cancellation is open or about where the link goes.

The token clears where cancellation is closed, so a surface that prints it never shows a link that would refuse on arrival. The link stops working at the cancellation deadline, so the replacement carries the time left as a max age, and is not cacheable at all where no deadline is known.

Why the mail's own mechanism does not cover this. The confirmation mail carries the link as [orchestra-notification:link], the notification's generic link, and OrderNotifier picks the template from whether that link exists: a booking that cannot be canceled gets the plain confirmed template, which has no cancel section at all. That is how the mail avoids a dead button, and it works only because a notifier can choose between templates. A surface that renders inline, such as the confirmation screen or an account view, has no such choice. That is what this token is for: it renders nothing at all when the window is closed.

Remaining tasks

None. Placing the token in the shipped workflow message is left to whoever wants it there.

User interface changes

None by itself. It makes the link available to any surface that wants it.

API changes

Two new tokens. [yoyaku-order:cancel-url] is the bare signed address, for a template that builds its own link. [yoyaku-order:cancel-link] is the same address as a ready anchor, for a message that prints what it is handed: an empty answer renders nothing at all, which is what a surface that cannot switch templates needs. Both are empty when the booking cannot be canceled.

OrderTokenHooks takes CancelLinkBuilder and the time service, and the replacement carries the time left before the cancellation deadline as a max age.

Data model changes

None.

AI-Generated: Yes (Claude Code was used to help draft this issue summary and to write the code and tests on the merge request. I reviewed and ran the work myself before posting it.)

Issue fork yoyaku-3620301

Command icon 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

mably created an issue. See original summary.

mably’s picture

Status: Active » Needs review
mably’s picture

Issue summary: View changes
mably’s picture

Issue summary: View changes

  • mably committed acf0f0d4 on 1.x
    feat: #3620301 Offer the cancel link on any surface, not only in the...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.