Three related changes on /member/account:
1. Payment History section now renders when contributionAmount > 0 OR
past payments exist. Previously a paid member who switched to $0 lost
visibility of their own past charges.
2. New "Next charge: $X on DATE" row renders above the transaction list
when nextPaymentDate is available, using --candle dashed border.
3. server/api/helcim/subscription.get.js now reads dateBilling from
Helcim's GET response and handles data as either object or array.
Helcim's real shape is {data: {id, dateBilling, ...}} — the old code
expected {data: [{nextBillingDate}]} and returned empty strings, so
the Membership-card "Next payment" row never rendered for members
whose cached date was missing. subscription.post.js and
update-contribution.post.js have the same wrong field name in their
CREATE flows; left for a follow-up — the GET refresh masks it.
Manual edit-flow and admin-flow tests also recorded in
docs/LAUNCH_READINESS.md.
60 lines
2.2 KiB
JavaScript
60 lines
2.2 KiB
JavaScript
// Refresh the authenticated member's cached nextBillingDate from Helcim.
|
|
// The account page calls this only when the stored date is stale (missing,
|
|
// past, or within ~24h). On success, writes the fresh date back to the member
|
|
// record so subsequent loads can render instantly from /api/auth/member.
|
|
//
|
|
// On Helcim errors, returns { subscription: null, error: 'unavailable' } (HTTP 200)
|
|
// so the client can fall back to the cached value (if any) without crashing.
|
|
import { requireAuth } from '../../utils/auth.js'
|
|
import { getHelcimSubscription } from '../../utils/helcim.js'
|
|
import Member from '../../models/member.js'
|
|
import { connectDB } from '../../utils/mongoose.js'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const member = await requireAuth(event)
|
|
|
|
if (!member.helcimSubscriptionId) {
|
|
return { subscription: null }
|
|
}
|
|
|
|
try {
|
|
const response = await getHelcimSubscription(member.helcimSubscriptionId)
|
|
const data = response?.data
|
|
const subscription = Array.isArray(data)
|
|
? data[0]
|
|
: (data && typeof data === 'object' ? data : response)
|
|
|
|
// Helcim's GET /subscriptions/:id returns `dateBilling` (YYYY-MM-DD).
|
|
// POST /subscriptions responses have sometimes been seen with `nextBillingDate`;
|
|
// accept both so the refresh works regardless of shape.
|
|
const nextBillingDate = subscription?.dateBilling || subscription?.nextBillingDate || null
|
|
|
|
if (nextBillingDate) {
|
|
const parsed = new Date(nextBillingDate)
|
|
if (!Number.isNaN(parsed.getTime())) {
|
|
await connectDB()
|
|
await Member.findByIdAndUpdate(
|
|
member._id,
|
|
{ $set: { nextBillingDate: parsed } },
|
|
{ runValidators: false }
|
|
)
|
|
}
|
|
}
|
|
|
|
return {
|
|
subscription: subscription
|
|
? {
|
|
id: String(subscription.id ?? ''),
|
|
status: subscription.status || '',
|
|
nextBillingDate: nextBillingDate || '',
|
|
}
|
|
: null,
|
|
}
|
|
} catch (error) {
|
|
console.error('[subscription.get] Helcim lookup failed', {
|
|
helcimSubscriptionId: member.helcimSubscriptionId,
|
|
error: error?.message || error,
|
|
})
|
|
return { subscription: null, error: 'unavailable' }
|
|
}
|
|
})
|