Credit students for cancelled paid lessons
CI / Tests (PHP 8.1) (pull_request) Successful in 47s
CI / Tests (PHP 8.2) (pull_request) Successful in 47s
CI / PHPStan (pull_request) Successful in 3m12s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m42s
CI / Build Plugin Zip (pull_request) Skipped
CI / No Debug Code (pull_request) Successful in 3s
CI / Coding Standards (pull_request) Successful in 2m52s
CI / Tests (PHP 8.1) (pull_request) Successful in 47s
CI / Tests (PHP 8.2) (pull_request) Successful in 47s
CI / PHPStan (pull_request) Successful in 3m12s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m42s
CI / Build Plugin Zip (pull_request) Skipped
CI / No Debug Code (pull_request) Successful in 3s
CI / Coding Standards (pull_request) Successful in 2m52s
Cancelling a lesson that was already paid for now credits the student that money instead of leaving it as a manual refund, and the daily scheduled-billing scan applies any available credit against their due charges before emailing the notice. - New us_credits ledger + us_payments.credit_applied column (Payment::netDue). - PaymentService::creditForCancelledLesson issues a per-lesson share of the covering payment's total; wired into all three cancel paths (student self-cancel, instructor status update, admin student-detail cancel). - PaymentService::applyCredits draws credit down FIFO across a run's charges, marking a fully-covered charge paid-by-credit; the notice shows the credit applied and reduced total, and the admin queue shows net due. - Student detail page shows a student's credit balance and history. Ships as part of the unreleased 1.2.0 (same release as scheduled billing). Tests: composer test (585), composer lint, composer cs all pass. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
@@ -17,9 +17,10 @@ class PaymentDueMailer {
|
||||
* on a lump-sum e-transfer so the studio can reconcile it to these payments.
|
||||
*
|
||||
* @param list<array{label: string, amount: float, currency: string, due_date: ?string, etransfer_email: ?string}> $items
|
||||
* @param float $creditApplied Account credit deducted from the total this notice covers.
|
||||
* @return bool False when there is no recipient or nothing to bill.
|
||||
*/
|
||||
public function send( \WP_User $student, array $items, string $reference = '' ): bool {
|
||||
public function send( \WP_User $student, array $items, string $reference = '', float $creditApplied = 0.0 ): bool {
|
||||
if ( '' === (string) $student->user_email || [] === $items ) {
|
||||
return false;
|
||||
}
|
||||
@@ -48,16 +49,30 @@ class PaymentDueMailer {
|
||||
}
|
||||
}
|
||||
|
||||
$body = __( 'You have upcoming payments due:', 'unsupervised-schedular' ) . "\n\n"
|
||||
. implode( "\n", $lines ) . "\n\n"
|
||||
. sprintf(
|
||||
/* translators: 1: currency, 2: total amount */
|
||||
__( 'Total due: %1$s %2$s', 'unsupervised-schedular' ),
|
||||
$currency,
|
||||
number_format( $total, 2 )
|
||||
);
|
||||
// Account credit (from an earlier cancelled paid lesson) offsets the total.
|
||||
$creditApplied = round( min( $creditApplied, $total ), 2 );
|
||||
$dueTotal = round( $total - $creditApplied, 2 );
|
||||
|
||||
if ( [] !== $emails ) {
|
||||
$body = __( 'You have upcoming payments due:', 'unsupervised-schedular' ) . "\n\n"
|
||||
. implode( "\n", $lines );
|
||||
|
||||
if ( $creditApplied > 0.0 ) {
|
||||
$body .= "\n\n" . sprintf(
|
||||
/* translators: 1: currency, 2: credit amount */
|
||||
__( 'Account credit applied: -%1$s %2$s', 'unsupervised-schedular' ),
|
||||
$currency,
|
||||
number_format( $creditApplied, 2 )
|
||||
);
|
||||
}
|
||||
|
||||
$body .= "\n\n" . sprintf(
|
||||
/* translators: 1: currency, 2: total amount */
|
||||
__( 'Total due: %1$s %2$s', 'unsupervised-schedular' ),
|
||||
$currency,
|
||||
number_format( $dueTotal, 2 )
|
||||
);
|
||||
|
||||
if ( $dueTotal > 0.0 && [] !== $emails ) {
|
||||
$body .= "\n\n" . sprintf(
|
||||
/* translators: %s: e-transfer destination email address(es) */
|
||||
__( 'Please send your e-transfer to: %s', 'unsupervised-schedular' ),
|
||||
|
||||
Reference in New Issue
Block a user