fix(reconcile): pass customerCode (not helcimCustomerId) to Helcim transactions API
This commit is contained in:
parent
4d44e7045c
commit
3c38333dd1
2 changed files with 16 additions and 5 deletions
|
|
@ -69,10 +69,12 @@ export default defineEventHandler(async (event) => {
|
|||
// Opportunistic backfill: members predating the helcimCustomerCode field
|
||||
// get it filled in here so the daily cron acts as the migration. Only on
|
||||
// the missing path — no overwrite, no extra API call once populated.
|
||||
if (!member.helcimCustomerCode) {
|
||||
let customerCode = member.helcimCustomerCode
|
||||
if (!customerCode) {
|
||||
try {
|
||||
const customer = await getHelcimCustomer(member.helcimCustomerId)
|
||||
if (customer?.customerCode) {
|
||||
customerCode = customer.customerCode
|
||||
await Member.findByIdAndUpdate(
|
||||
member._id,
|
||||
{ $set: { helcimCustomerCode: customer.customerCode } },
|
||||
|
|
@ -85,9 +87,14 @@ export default defineEventHandler(async (event) => {
|
|||
}
|
||||
}
|
||||
|
||||
if (!customerCode) {
|
||||
console.warn(`[reconcile] no customerCode for member=${member._id}; skipping`)
|
||||
return { error: false, txExamined: 0, created: 0, existed: 0, skipped: 0 }
|
||||
}
|
||||
|
||||
let txs
|
||||
try {
|
||||
txs = await listTransactionsWithRetry(member.helcimCustomerId)
|
||||
txs = await listTransactionsWithRetry(customerCode)
|
||||
} catch (err) {
|
||||
console.error(`[reconcile] member=${member._id}: ${err?.message || err}`)
|
||||
return { error: true }
|
||||
|
|
|
|||
|
|
@ -167,8 +167,8 @@ describe('POST /api/internal/reconcile-payments', () => {
|
|||
// m1 succeeds first try, m2 fails all 3 retries, m3 succeeds first try.
|
||||
// Keyed by customerCode so it works regardless of call order (chunked Promise.all).
|
||||
listHelcimCustomerTransactions.mockImplementation((customerCode) => {
|
||||
if (customerCode === 'cust-1') return Promise.resolve([{ id: 'tx1', status: 'paid', amount: 5 }])
|
||||
if (customerCode === 'cust-3') return Promise.resolve([{ id: 'tx3', status: 'paid', amount: 7 }])
|
||||
if (customerCode === 'CST-1') return Promise.resolve([{ id: 'tx1', status: 'paid', amount: 5 }])
|
||||
if (customerCode === 'CST-3') return Promise.resolve([{ id: 'tx3', status: 'paid', amount: 7 }])
|
||||
return Promise.reject(new Error('helcim 503'))
|
||||
})
|
||||
upsertPaymentFromHelcim.mockResolvedValue({ created: true, payment: { _id: 'p' } })
|
||||
|
|
@ -291,6 +291,7 @@ describe('POST /api/internal/reconcile-payments', () => {
|
|||
{ $set: { helcimCustomerCode: 'CST-NEW' } },
|
||||
{ runValidators: false }
|
||||
)
|
||||
expect(listHelcimCustomerTransactions).toHaveBeenCalledWith('CST-NEW')
|
||||
})
|
||||
|
||||
it('skips backfill when helcimCustomerCode is already present', async () => {
|
||||
|
|
@ -308,6 +309,7 @@ describe('POST /api/internal/reconcile-payments', () => {
|
|||
|
||||
expect(getHelcimCustomer).not.toHaveBeenCalled()
|
||||
expect(Member.findByIdAndUpdate).not.toHaveBeenCalled()
|
||||
expect(listHelcimCustomerTransactions).toHaveBeenCalledWith('CST-EXISTING')
|
||||
})
|
||||
|
||||
it('does not fail the run when getHelcimCustomer throws during backfill', async () => {
|
||||
|
|
@ -325,7 +327,9 @@ describe('POST /api/internal/reconcile-payments', () => {
|
|||
const result = await reconcileHandler(event)
|
||||
|
||||
expect(Member.findByIdAndUpdate).not.toHaveBeenCalled()
|
||||
expect(result.memberErrors).toBe(0) // backfill failure is best-effort, not fatal
|
||||
// Without a customerCode, we skip the transactions API entirely (best-effort, not error).
|
||||
expect(listHelcimCustomerTransactions).not.toHaveBeenCalled()
|
||||
expect(result.memberErrors).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue