diff --git a/app/(app)/clients/new.tsx b/app/(app)/clients/new.tsx index 85409dc..39943b6 100644 --- a/app/(app)/clients/new.tsx +++ b/app/(app)/clients/new.tsx @@ -151,25 +151,26 @@ export default function NewClientScreen() { startDate: new Date().toISOString(), }); - // 3. Create installation ticket - const ticketRes = await api.post('/api/v1/tickets', { - clientId: client.id, - subject: `New Installation — ${firstName.trim()} ${lastName.trim()}`, - type: 'INSTALLATION', - priority: 'NORMAL', - // Pass subType so activation ticket knows to gate on payment for PREPAID - ...(subType === 'PREPAID' ? { priority: 'HIGH' } : {}), - }); - const ticket = ticketRes.data; + // 3. Fetch the auto-created installation ticket (API creates one on client creation) + let ticket: any = null; + try { + const ticketsRes = await api.get(`/api/v1/tickets?clientId=${client.id}&type=INSTALLATION&limit=1`); + const items = ticketsRes.data?.data ?? ticketsRes.data ?? []; + ticket = items[0] ?? null; + } catch {} Alert.alert( 'Client Onboarded! 🎉', `${firstName} ${lastName} has been registered.\n\nAn installation ticket has been created.`, [{ - text: 'View Ticket', + text: ticket ? 'View Ticket' : 'View Client', onPress: () => { - router.replace('/(app)/clients'); - setTimeout(() => router.push(`/(app)/tasks/${ticket.id}`), 300); + if (ticket) { + router.replace('/(app)/clients'); + setTimeout(() => router.push(`/(app)/tasks/${ticket.id}`), 300); + } else { + router.replace('/(app)/clients'); + } }, }, { text: 'Done', diff --git a/app/(app)/leads/[id].tsx b/app/(app)/leads/[id].tsx index f93b9e0..3c5c511 100644 --- a/app/(app)/leads/[id].tsx +++ b/app/(app)/leads/[id].tsx @@ -72,14 +72,13 @@ export default function LeadDetailScreen() { }); const client = clientRes.data; - // Create installation ticket - const ticketRes = await api.post('/api/v1/tickets', { - clientId: client.id, - subject: `New Installation — ${lead.firstName} ${lead.lastName !== '—' ? lead.lastName : ''}`.trim(), - type: 'INSTALLATION', - priority: 'NORMAL', - }); - const ticket = ticketRes.data; + // Fetch the auto-created installation ticket (API creates one on client creation) + let ticket: any = null; + try { + const tRes = await api.get(`/api/v1/tickets?clientId=${client.id}&type=INSTALLATION&limit=1`); + const items = tRes.data?.data ?? tRes.data ?? []; + ticket = items[0] ?? null; + } catch {} // Mark lead as CONVERTED await api.patch(`/api/v1/leads/${id}`, { diff --git a/app/(app)/tasks/[id].tsx b/app/(app)/tasks/[id].tsx index bce78ed..95e4cbb 100644 --- a/app/(app)/tasks/[id].tsx +++ b/app/(app)/tasks/[id].tsx @@ -147,13 +147,12 @@ export default function TicketDetailScreen() { : `Installation confirmed. Location recorded: ${coordStr}`; await api.post(`/api/v1/tickets/${id}/messages`, { body: note }).catch(() => {}); - // 4. Create follow-up activation ticket + // 4. Create follow-up activation ticket (non-fatal if fails for role reasons) await api.post('/api/v1/tickets', { - clientId: ticket?.clientId, - subject: `Account Activation — ${ticket?.client?.firstName ?? ''} ${ticket?.client?.lastName ?? ''}`.trim(), - type: 'BILLING', - priority: 'NORMAL', - description: `Follow-up after installation confirmed. Please activate the client account and generate the first invoice.\n\nInstallation ref: ${id}\nLocation: ${coordStr}`, + clientId: ticket?.clientId, + subject: `Account Activation — ${ticket?.client?.firstName ?? ''} ${ticket?.client?.lastName ?? ''}`.trim(), + type: 'BILLING', + priority: 'NORMAL', }).catch(() => {}); setInstNotes(''); @@ -222,17 +221,26 @@ export default function TicketDetailScreen() { const planPrice = Number(sub?.monthlyPrice ?? 0); const submitPrepaidPayment = async () => { - const amt = parseFloat(prepaidPayAmount); + const effectiveAmount = prepaidPayAmount || String(planPrice); + const amt = parseFloat(effectiveAmount); if (!amt || amt <= 0) { Alert.alert('Invalid Amount', 'Enter a valid amount.'); return; } setPrepaidPaying(true); try { - // 1. Record payment + // 1. Generate first invoice for client + let invoiceId: string | undefined; + try { + const invRes = await api.post(`/api/v1/invoices/generate/${ticket.clientId}`); + invoiceId = invRes.data?.id; + } catch {} + + // 2. Record payment (link to invoice if available) await api.post('/api/v1/payments', { clientId: ticket.clientId, amount: amt, channel: prepaidPayMethod, paymentDate: new Date().toISOString(), notes: 'First prepaid payment — account activation', + ...(invoiceId ? { invoiceId } : {}), }); // 2. Activate subscription if (sub?.id) { @@ -366,11 +374,11 @@ export default function TicketDetailScreen() { {/* Amount */} Amount {/* Method */} @@ -388,7 +396,7 @@ export default function TicketDetailScreen() {