Quote a monthly private lesson per lesson, a group class monthly
CI / Tests (PHP 8.1) (pull_request) Successful in 53s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m42s
CI / Build Plugin Zip (pull_request) Skipped
CI / Tests (PHP 8.2) (pull_request) Successful in 54s
CI / Coding Standards (pull_request) Successful in 2m52s
CI / PHPStan (pull_request) Successful in 3m0s
CI / Tests (PHP 8.1) (pull_request) Successful in 53s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m42s
CI / Build Plugin Zip (pull_request) Skipped
CI / Tests (PHP 8.2) (pull_request) Successful in 54s
CI / Coding Standards (pull_request) Successful in 2m52s
CI / PHPStan (pull_request) Successful in 3m0s
A monthly charge covers every lesson that falls in the month, so a private lesson's fee reads "50.00 CAD per lesson monthly" — the figure on its own would suggest the whole month costs 50.00. A group class is enrolled in once, as a single schedule, so its price is quoted as the monthly figure it is. The pay agreement follows the same split: per-lesson for a monthly private lesson, the monthly figure for a monthly group class. Weekly, full-term and at-booking wording is unchanged. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -489,6 +489,7 @@
|
||||
price: offering.price,
|
||||
currency: offering.currency,
|
||||
billing_mode: offering.billing_mode,
|
||||
kind: offering.kind,
|
||||
occurrences: weeklyEl && weeklyEl.checked ? weeklyOccurrences(slot) : 1,
|
||||
})
|
||||
: '';
|
||||
|
||||
+33
-8
@@ -36,6 +36,14 @@
|
||||
return CADENCE[billingMode] ? billingMode : 'one_time';
|
||||
}
|
||||
|
||||
// A monthly charge rolls up every lesson that falls in the month, so a
|
||||
// private lesson's monthly price is quoted *per lesson* — the fee is
|
||||
// multiplied by the lessons booked that month. A group class is enrolled in
|
||||
// once, as one schedule, so its monthly figure is quoted as it stands.
|
||||
function isPerLessonMonthly(billingMode, kind) {
|
||||
return 'monthly' === billingMode && 'group_class' !== kind;
|
||||
}
|
||||
|
||||
// "50.00 CAD" — amount then currency code, the format used throughout the
|
||||
// ledger, receipts and payment notices.
|
||||
function money(amount, currency) {
|
||||
@@ -57,22 +65,26 @@
|
||||
return (Number(amount) || 0) + tax(amount);
|
||||
}
|
||||
|
||||
// "50.00 CAD at booking" / "Free" — the catalogue label, always carrying the
|
||||
// cadence so a price is never shown without saying when it is due.
|
||||
// "50.00 CAD at booking" / "50.00 CAD per lesson monthly" / "Free" — the
|
||||
// catalogue label, always carrying the cadence so a price is never shown
|
||||
// without saying when it is due.
|
||||
function priceLabel(offering) {
|
||||
const price = Number(offering.price) || 0;
|
||||
if (price <= 0) {
|
||||
return 'Free';
|
||||
}
|
||||
|
||||
return `${money(price, offering.currency)} ${CADENCE[mode(offering.billing_mode)]}`;
|
||||
const billingMode = mode(offering.billing_mode);
|
||||
const perLesson = isPerLessonMonthly(billingMode, offering.kind) ? 'per lesson ' : '';
|
||||
|
||||
return `${money(price, offering.currency)} ${perLesson}${CADENCE[billingMode]}`;
|
||||
}
|
||||
|
||||
// The price block shown on a booking/enrolment form, followed by the
|
||||
// agreement the student must tick to confirm they will pay it. A free
|
||||
// offering has nothing to agree to, so it renders nothing at all.
|
||||
//
|
||||
// opts: { price, currency, billing_mode, occurrences }
|
||||
// opts: { price, currency, billing_mode, kind, occurrences }
|
||||
// `occurrences` is how many lessons a one-time price is charged for in this
|
||||
// one registration (a weekly reservation claims several at once); it is
|
||||
// ignored for the other modes, whose price is charged per period regardless.
|
||||
@@ -96,7 +108,7 @@
|
||||
<h4>Price</h4>
|
||||
<p class="us-price-amount">
|
||||
<strong>${escHtml(money(price, currency))}</strong>
|
||||
<span class="us-price-cadence">${escHtml(CADENCE[billingMode])}</span>
|
||||
<span class="us-price-cadence">${escHtml(cadenceLabel(billingMode, opts.kind))}</span>
|
||||
</p>
|
||||
${taxLine}
|
||||
<p class="us-price-note">${escHtml(count > 1
|
||||
@@ -104,18 +116,31 @@
|
||||
: CADENCE_NOTE[billingMode])}</p>
|
||||
<label class="us-price-agree">
|
||||
<input type="checkbox" class="us-price-accept" required>
|
||||
${escHtml(agreeText(each, currency, billingMode, count))}
|
||||
${escHtml(agreeText(each, currency, billingMode, count, opts.kind))}
|
||||
</label>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
// The cadence as it reads beside an amount: a private lesson billed monthly
|
||||
// adds "per lesson", since the month's charge is that fee times the lessons
|
||||
// it covers.
|
||||
function cadenceLabel(billingMode, kind) {
|
||||
return isPerLessonMonthly(billingMode, kind)
|
||||
? `per lesson ${CADENCE[billingMode]}`
|
||||
: CADENCE[billingMode];
|
||||
}
|
||||
|
||||
// What the student is ticking: the amount actually billed (tax included),
|
||||
// and when. A weekly reservation is charged per lesson for every week it
|
||||
// claims, and the claim can come up short when another student takes one of
|
||||
// the times first — so its total is stated as a ceiling, never a promise.
|
||||
function agreeText(each, currency, billingMode, count) {
|
||||
function agreeText(each, currency, billingMode, count, kind) {
|
||||
if (RECURRING.indexOf(billingMode) !== -1) {
|
||||
return `I agree to pay ${money(each, currency)} per lesson, billed ${CADENCE[billingMode]}.`;
|
||||
// A monthly group class is enrolled in once and quoted as it stands;
|
||||
// everything else recurring is a per-lesson fee.
|
||||
return 'monthly' === billingMode && !isPerLessonMonthly(billingMode, kind)
|
||||
? `I agree to pay ${money(each, currency)} monthly.`
|
||||
: `I agree to pay ${money(each, currency)} per lesson, billed ${CADENCE[billingMode]}.`;
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
|
||||
Reference in New Issue
Block a user