Files
unsupervised-scheduler/templates/admin/payments.php
thatguygriffandClaude Opus 4.8 4328e8fb5f
CI / Tests (PHP 8.2) (pull_request) Successful in 39s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m12s
CI / No Debug Code (pull_request) Successful in 3s
CI / PHPStan (pull_request) Successful in 2m52s
CI / Coding Standards (pull_request) Successful in 2m54s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m39s
CI / Build Plugin Zip (pull_request) Skipped
Add weekly and monthly scheduled billing for offerings
Offerings can now bill weekly (a pending payment 24h before each lesson)
or monthly (one payment on the 1st for that month's lessons), alongside
one-time and full-term. Applies to both private lessons and group classes.

- Offering: new `weekly`/`monthly` billing modes + `isScheduledBilling()`
- Booking/enrolment defer payment for scheduled modes; a single lesson
  booked after its due date has passed (e.g. an add-on in an already-billed
  month) is charged at booking instead
- ScheduledBillingRunner: daily WP-Cron scan generates due payments across
  four cases (private/group × weekly/monthly), deduped via lesson.payment_id
  and payments.period_key
- PaymentDueMailer: one consolidated itemised email per student per scan
- Notice batch: payments emailed together share a reference; the admin
  Payments queue groups them with a lump-sum total for e-transfer reconciliation
- Cancellation never voids a scheduled payment (Payment::isScheduled())
- Schema: us_payments gains due_date, period_key, notice_batch; USC_VERSION 1.2.0

composer test, composer lint, composer cs all pass.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-24 12:06:37 -03:00

69 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
if (! defined('ABSPATH')) {
exit;
}
/** @var list<array{reference: string, is_group: bool, total: string, rows: list<array{id: int, student: string, amount: string, method: string, for: string, etransfer_email: string}>}> $groups */
?>
<div class="wrap">
<h1><?php esc_html_e('Payments', 'unsupervised-schedular'); ?></h1>
<p class="description"><?php esc_html_e('Pending payments awaiting confirmation. Marking one received confirms the booking and emails a receipt. You can correct the e-transfer email here if the student sent it elsewhere. Payments billed together on one notice are grouped under a reference — a single lump-sum e-transfer covers every payment in the group.', 'unsupervised-schedular'); ?></p>
<?php if (empty($groups)) : ?>
<p><?php esc_html_e('No pending payments.', 'unsupervised-schedular'); ?></p>
<?php else : ?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php esc_html_e('Student', 'unsupervised-schedular'); ?></th>
<th><?php esc_html_e('For', 'unsupervised-schedular'); ?></th>
<th><?php esc_html_e('Amount', 'unsupervised-schedular'); ?></th>
<th><?php esc_html_e('Method', 'unsupervised-schedular'); ?></th>
<th><?php esc_html_e('E-transfer email', 'unsupervised-schedular'); ?></th>
<th><?php esc_html_e('Actions', 'unsupervised-schedular'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($groups as $group) : ?>
<?php if ($group['is_group']) : ?>
<tr>
<td colspan="6" style="background:#f0f6fc;">
<?php
printf(
/* translators: 1: notice reference code, 2: lump-sum total, 3: number of payments. */
esc_html__('Grouped notice %1$s — one lump-sum e-transfer of %2$s covers the %3$d payments below.', 'unsupervised-schedular'),
'<strong>' . esc_html($group['reference']) . '</strong>',
'<strong>' . esc_html($group['total']) . '</strong>',
count($group['rows'])
);
?>
</td>
</tr>
<?php endif; ?>
<?php foreach ($group['rows'] as $row) : ?>
<tr>
<form method="post">
<?php wp_nonce_field('usc_payment_action'); ?>
<input type="hidden" name="usc_action" value="mark_paid">
<input type="hidden" name="payment_id" value="<?php echo esc_attr((string) $row['id']); ?>">
<td><?php echo esc_html($row['student']); ?></td>
<td><?php echo esc_html($row['for']); ?></td>
<td><?php echo esc_html($row['amount']); ?></td>
<td><?php echo esc_html($row['method']); ?></td>
<td><input type="email" name="etransfer_email" class="regular-text" value="<?php echo esc_attr($row['etransfer_email']); ?>"></td>
<td>
<button type="submit" class="button button-small button-primary">
<?php esc_html_e('Mark received', 'unsupervised-schedular'); ?>
</button>
</td>
</form>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>