Files
unsupervised-scheduler/templates/admin/payments.php
T
thatguygriff 6c4097b385
CI / Tests (PHP 8.1) (pull_request) Successful in 45s
CI / Tests (PHP 8.3) (pull_request) Successful in 50s
CI / No Debug Code (pull_request) Successful in 3s
CI / Coding Standards (pull_request) Successful in 1m2s
CI / Tests (PHP 8.2) (pull_request) Successful in 1m0s
CI / PHPStan (pull_request) Successful in 1m4s
CI / Build Plugin Zip (pull_request) Has been skipped
Add payments foundation (e-transfer/comp, Stripe config, receipts)
Implements the payments foundation for #7. Without Stripe credentials
everything works on e-transfer (pending payment confirmed by a studio
admin); when Stripe keys are configured the default flips to credit card.
Per-student override (card/etransfer/comp) is set on the student detail.

- Schema: us_payments (amount DECIMAL dollars, method, status, receipt,
  stripe intent id).
- src/Payment/: Payment VO, PaymentRepository, StudioSettings (Stripe
  options + isStripeConfigured + settings page), BillingMethodResolver
  (per-student override; default card if configured else etransfer),
  ReceiptMailer, PaymentService (create at registration, link payment_id,
  comp->paid+confirm, markPaid->confirm+receipt), PaymentController
  (e-transfer confirmation queue), PaymentEndpoint (PATCH /payments/{id}).
- Booking + enrolment create the payment from the offering price; comp
  auto-confirms the lesson; setPaymentId on both repositories.
- Admin: Studio Settings + Payments menus (manage_billing); per-student
  billing method on the student detail page.
- Docs: payments.md + README updated.

Deferred to a follow-up: the live Stripe card charge (PaymentIntent +
Stripe.js Elements + webhook + stripe/stripe-php). Until then a card
payment is created pending and confirmed like an e-transfer.

Tests: tests/Unit/Payment/ (VO, repository, resolver, service, mailer).
composer test (147), cs, and PHPStan level 6 all pass.

Refs #7

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 10:24:01 -03:00

50 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
if (! defined('ABSPATH')) {
exit;
}
/** @var list<array{id: int, student: string, amount: string, method: string, for: string}> $rows */
?>
<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.', 'unsupervised-schedular'); ?></p>
<?php if (empty($rows)) : ?>
<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('Actions', 'unsupervised-schedular'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($rows as $row) : ?>
<tr>
<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>
<form method="post" style="display:inline;">
<?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']); ?>">
<button type="submit" class="button button-small button-primary">
<?php esc_html_e('Mark received', 'unsupervised-schedular'); ?>
</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</div>