import { billingCycleForSchedule, scheduleValue } from './billingSchedule'; interface Category { id: string | number; name?: string | null; } interface Template { name?: string | null; categoryKeywords?: string[]; } // The source bill a draft is seeded from. The specific fields the draft reads // are declared; the index signature carries every other field through the spread. export interface SourceBill { id?: string | number | null; name?: string | null; category_id?: string | number | null; due_day?: number | null; expected_amount?: number | null; cycle_type?: string | null; billing_cycle?: string | null; cycle_day?: string | number | null; autopay_enabled?: unknown; autodraft_status?: string | null; auto_mark_paid?: unknown; has_2fa?: unknown; snowball_include?: unknown; snowball_exempt?: unknown; [key: string]: unknown; } interface MakeBillDraftOptions { copy?: boolean; template?: Template | null; categories?: Category[]; } function categoryForTemplate(template: Template | null | undefined, categories: Category[] = []): string | number | null { const keywords = template?.categoryKeywords || []; const match = categories.find(category => { const name = String(category.name || '').toLowerCase(); return keywords.some(keyword => name.includes(keyword)); }); return match?.id ?? null; } function categoryIdOrFallback( categoryId: string | number | null | undefined, template: Template | null, categories: Category[] = [], ): string | number | null { if (categoryId && categories.some(category => String(category.id) === String(categoryId))) { return categoryId; } return template ? categoryForTemplate(template, categories) : null; } export function makeBillDraft(source: SourceBill | null | undefined, { copy = false, template = null, categories = [] }: MakeBillDraftOptions = {}): SourceBill { const data: SourceBill = source || {}; return { ...data, id: undefined, source_bill_id: copy && data.id != null ? data.id : undefined, active: 1, name: copy ? `${data.name || 'Bill'} (Copy)` : (data.name || template?.name || ''), category_id: categoryIdOrFallback(data.category_id, template, categories), due_day: data.due_day || 1, expected_amount: data.expected_amount ?? 0, billing_cycle: billingCycleForSchedule(scheduleValue(data)), cycle_type: scheduleValue(data), cycle_day: String(data.cycle_day || '1'), autopay_enabled: !!data.autopay_enabled, autodraft_status: data.autodraft_status || (data.autopay_enabled ? 'assumed_paid' : 'none'), auto_mark_paid: !!data.auto_mark_paid, has_2fa: !!data.has_2fa, snowball_include: !!data.snowball_include, snowball_exempt: !!data.snowball_exempt, }; } /** The pre-filled draft object produced by makeBillDraft (fed to BillModal's `initialBill`). */ export type BillDraft = ReturnType;