Implement catalog CRUD overhaul, snapshot fallback activation, and billing/UX hardening

This commit is contained in:
Dwindi Ramadhana
2026-02-17 00:03:35 +07:00
parent e6aef31dd1
commit 2726b6c312
37 changed files with 2936 additions and 204 deletions

View File

@@ -0,0 +1,129 @@
# Billing Cooldown Runtime Checklist (Staging)
## Scope
Validate these behaviors end-to-end:
1. `pending_cooldown` lock on new checkout (120s)
2. Continue pending payment via `Pay` button
3. PayPal/Pakasir webhook delay handling
4. Auto-status transition from `pending` to `paid`
## Preconditions
1. Staging is deployed with latest billing changes.
2. Config is refreshed:
- `php artisan optimize:clear`
- `php artisan config:cache`
3. Env includes:
- `DEWEMOJI_CHECKOUT_PENDING_COOLDOWN=120`
4. Webhooks are configured and reachable:
- PayPal webhook endpoint
- Pakasir webhook endpoint
5. Test account available (verified email, logged in).
## Quick Observability
1. Browser devtools open (`Network` tab).
2. Keep Billing page open in another tab for status checks.
3. Optional server logs tail:
- `tail -f storage/logs/laravel.log`
## Test Matrix
### A. Cooldown Lock (PayPal)
1. Start Personal checkout in USD.
2. Before webhook settles, try starting another checkout from Pricing.
3. Expected:
- API returns `409` with `error: pending_cooldown`.
- UI shows wait message with countdown (`retry_after` seconds).
- Checkout CTA stays disabled until countdown reaches 0.
### B. Cooldown Lock (Pakasir)
1. Start Personal checkout in IDR (QRIS modal opens).
2. Close/cancel modal only if needed for this test case.
3. Immediately try another new checkout from Pricing.
4. Expected:
- API returns `409 pending_cooldown`.
- UI countdown appears and blocks new checkout.
### C. Continue Pending (PayPal)
1. Create a PayPal pending payment.
2. Go to `/dashboard/billing`.
3. Click `Pay` on pending row.
4. Expected:
- Redirect to PayPal approve URL.
- No new payment row created just for resume action.
### D. Continue Pending (Pakasir)
1. Create a Pakasir pending payment.
2. Go to `/dashboard/billing`.
3. Click `Pay` on pending row.
4. Expected:
- QR modal opens with amount + expiry.
- Polling runs and closes modal when status becomes paid.
### E. Webhook Delay UX
1. Complete payment at provider.
2. Observe app while webhook is delayed.
3. Expected:
- Status may remain `pending` briefly.
- User can continue pending (`Pay` button).
- After webhook/poll settles: status updates to `paid`.
### F. Pending Timeout to New Checkout
1. Keep a payment pending beyond cooldown (`>=120s`).
2. Try new checkout from Pricing.
3. Expected:
- New checkout is allowed again.
- Existing behavior for replacing/canceling pending remains intact.
### G. Edge Responses
1. Try `Pay` on a row that is no longer pending (race condition).
2. Expected:
- UI handles response (`payment_not_pending`) and refreshes state safely.
3. If pending QR is expired:
- Expected `payment_expired`, prompt to start new checkout.
## API Assertions (Network)
Check response payloads:
1. Cooldown block:
```json
{
"error": "pending_cooldown",
"retry_after": 87,
"pending_payment_id": 123,
"provider": "paypal"
}
```
2. Resume PayPal:
```json
{
"ok": true,
"mode": "redirect",
"approve_url": "https://..."
}
```
3. Resume Pakasir:
```json
{
"ok": true,
"mode": "qris",
"payment_number": "...",
"order_id": "DW-...",
"expired_at": "..."
}
```
## Pass/Fail Sheet
| Check | Result | Notes |
|---|---|---|
| A. PayPal cooldown lock | | |
| B. Pakasir cooldown lock | | |
| C. Resume pending PayPal | | |
| D. Resume pending Pakasir | | |
| E. Webhook delay UX | | |
| F. New checkout after cooldown | | |
| G. Edge response handling | | |
## Exit Criteria
Release-ready when:
1. All rows above are `PASS`.
2. No uncaught JS errors in console.
3. No unexpected 5xx in network log during flow.