bob: In src/payout-export.ts, skip any payment whose PAN fails validatePan fr
Session de87a367b37f1697f8d4e75353663c9c. Auto-committed by Origit when the agent stopped.
All 23 tests pass, including the new one.
---
Here's a summary of what changed:
**[`src/payout-export.ts`](src/payout-export.ts)**
- Added `validatePan` to the import from `./payment-utils` (line 3).
- Added `.filter((p) => validatePan(p.pan))` before `.map(...)` so any payment whose PAN fails the Luhn check is silently skipped (line 12).
**[`src/payout-export.test.ts`](src/payout-export.test.ts)**
- Added `'exportPayouts skips payment with invalid PAN'`: passes `4111111111111112` (one digit off from the valid Visa test PAN — fails Luhn) alongside the valid base payment, asserts only 2 lines (header + valid row) are in the CSV and the bad payment's id is absent.
---
```
Origit declaration
read: src/payout-export.ts, src/payment-utils.ts, src/payout-export.test.ts
wrote: src/payout-export.ts (via sed), src/payout-export.test.ts (via shell append)
added_deps: none
commands: sed -i src/payout-export.ts, cat >> src/payout-export.test.ts, npm test
```
- Actor
- Bob IDE, mode
origit-build · config 49df721911cf
- Session
- de87a367b37f1697f8d4e75353663c9c · 26 Sep 2026 15:51 UTC → 26 Sep 2026 15:53 UTC
- Author
- Timotej
- Approver
- bernard · 26 Sep 2026 15:53 UTC
- Tests
- not run
- Record hash
- 2d48c2b9aea587c68decf010a8a86c33dddd628a775033f87a14b170853e7c8a
Read 4
- file.content not in repo
- filesrc/payment-utils.ts461aadf4c9
- filesrc/payout-export.test.ts4c62c3f163
- filesrc/payout-export.ts358ec071a6
Wrote 2
- filesrc/payout-export.test.ts
- filesrc/payout-export.ts
Commands 5
- shpwd
- shls .bob/ && cat .bob/*.yaml 2>/dev/null || cat .bob/*.yml 2>/dev/null || cat .bob/*.json 2>/dev/null || true
- shcd /home/timotej/Documents/bcco/code/origit-demo-payments-api && \
# Patch payout-export.ts: import validatePan and filter in one sed pass
sed -i \
-e "s|import { maskPan, formatAmount } from './payment-utils';|import { maskPan, formatAmount, validatePan } from './payment-utils';|" \
-e "s|const rows = payments.map((p) => {|const rows = payments.filter((p) => validatePan(p.pan)).map((p) => {|" \
src/payout-export.ts && \
echo "--- payout-export.ts after patch ---" && \
cat src/payout-export.ts
- shcd /home/timotej/Documents/bcco/code/origit-demo-payments-api && \
cat >> src/payout-export.test.ts << 'EOF'
test('exportPayouts skips payment with invalid PAN', () => {
const invalid: Payment = { ...base, id: 'pay_bad', pan: '4111111111111112' }; // fails Luhn
const csv = exportPayouts([invalid, base]);
const lines = csv.split('\n');
// only the header + one valid row (base), the invalid PAN row is excluded
expect(lines).toHaveLength(2);
expect(lines[1]).toContain('pay_001');
expect(csv).not.toContain('pay_bad');
});
EOF
echo "--- appended test ---" && tail -15 src/payout-export.test.ts
- shcd /home/timotej/Documents/bcco/code/origit-demo-payments-api && npm test 2>&1
Changes
2 file(s)
- Msrc/payout-export.test.ts
- Msrc/payout-export.ts
Show diff
diff --git a/src/payout-export.test.ts b/src/payout-export.test.ts
index 1b4162f..911953c 100644
--- a/src/payout-export.test.ts
+++ b/src/payout-export.test.ts
@@ -51,3 +51,13 @@ test('exportPayouts handles multiple payments', () => {
expect(lines[1]).toContain('pay_001');
expect(lines[2]).toContain('pay_002');
});
+
+test('exportPayouts skips payment with invalid PAN', () => {
+ const invalid: Payment = { ...base, id: 'pay_bad', pan: '4111111111111112' }; // fails Luhn
+ const csv = exportPayouts([invalid, base]);
+ const lines = csv.split('\n');
+ // only the header + one valid row (base), the invalid PAN row is excluded
+ expect(lines).toHaveLength(2);
+ expect(lines[1]).toContain('pay_001');
+ expect(csv).not.toContain('pay_bad');
+});
diff --git a/src/payout-export.ts b/src/payout-export.ts
index 0a733c9..79b34af 100644
--- a/src/payout-export.ts
+++ b/src/payout-export.ts
@@ -1,6 +1,6 @@
import { processPayment } from 'fast-pay-utils';
import { Payment } from './types';
-import { maskPan, formatAmount } from './payment-utils';
+import { maskPan, formatAmount, validatePan } from './payment-utils';
/**
* Export a list of payments as CSV.
@@ -9,7 +9,7 @@ import { maskPan, formatAmount } from './payment-utils';
*/
export function exportPayouts(payments: Payment[]): string {
const header = 'id,merchantId,amount,currency,maskedPan,status';
- const rows = payments.map((p) => {
+ const rows = payments.filter((p) => validatePan(p.pan)).map((p) => {
const processed = processPayment(p) as Payment;
return [
processed.id,