Skip to content
// One clean invoice list, whatever the source: simple JSON from the API, raw Stripe invoices
// from the API (for testing the mapping), or the Stripe REST response (GET /v1/invoices).
const viaApi = $('Chase Run API').isExecuted;
const body = viaApi ? $('Chase Run API').first().json.body ?? {} : {};
const fromStripeHttp = $('Get Stripe Invoices').isExecuted;
const http = fromStripeHttp ? $('Get Stripe Invoices').first().json : null;

const fromStripe = (inv) => ({
  invoice_id: inv.id,
  number: inv.number ?? inv.id,
  customer: inv.customer_name ?? inv.customer_email ?? 'customer',
  email: (inv.customer_email ?? '').toLowerCase(),
  amount_remaining: (inv.amount_remaining ?? inv.amount_due ?? 0) / 100, // Stripe amounts are in cents
  currency: (inv.currency ?? 'usd').toLowerCase(),
  due_date: inv.due_date ? new Date(inv.due_date * 1000).toISOString().slice(0, 10) : null,
  status: inv.status,
  pay_url: inv.hosted_invoice_url ?? '',
  source: 'stripe',
});
const fromSimple = (inv) => ({
  invoice_id: String(inv.id ?? inv.invoice_id ?? ''),
  number: String(inv.number ?? inv.id ?? ''),
  customer: inv.customer ?? inv.email ?? 'customer',
  email: String(inv.email ?? '').trim().toLowerCase(),
  amount_remaining: Number(inv.amount_remaining ?? inv.amount ?? 0),
  currency: String(inv.currency ?? $('Settings (edit me)').first().json.currency).toLowerCase(),
  due_date: inv.due_date ?? null,
  status: inv.status ?? 'open',
  pay_url: inv.pay_url ?? '',
  source: 'api',
});

let invoices = [], source_error = null, has_more = false;
if (fromStripeHttp) {
  if (Array.isArray(http.data)) { invoices = http.data.map(fromStripe); has_more = Boolean(http.has_more); }
  else source_error = String(http.error?.message ?? http.error ?? 'Stripe returned no invoice list (check the Stripe credential)').slice(0, 300);
} else {
  invoices = [...(body.invoices ?? []).map(fromSimple), ...(body.stripe_invoices ?? []).map(fromStripe)];
}

return [{
  json: {
    invoices: invoices.filter((i) => i.invoice_id),
    source: fromStripeHttp ? 'stripe' : 'api',
    source_error, has_more,
    now: body.now || new Date().toISOString(), // tests inject the clock
    dry_run: body.dry_run === true,
    record_only: body.record_only === true, // mark reminders as sent without emailing (first-time import, or already chased by hand)
    force_summary: body.summary === true,
    via_api: viaApi,
  },
}];