= 2; $can_delete = lookupUserPermission('module_sales') >= 3; // The money on it is accounting's too - Financial, with Sales at Read (billingMoneyCan()) $can_take_payment = billingMoneyCan('take') && invoiceCanPay($invoice, $state); $can_edit_payments = billingMoneyCan('edit'); $can_delete_payments = billingMoneyCan('delete'); $can_remind = billingMoneyCan('remind'); $can_edit_lines = billingCanEditItems('invoice', $invoice); $mail_ready = !empty($config_smtp_provider) && billingEmailableContacts('invoice', $client_id) > 0; $saved_card = $can_take_payment && in_array($status, ['Sent', 'Viewed'], true) && invoiceHasSavedCard($client_id); $unbilled_tickets = $can_edit && $can_edit_lines && $config_module_enable_ticketing ? count(billingUnbilledTickets($client_id)) : 0; // Expenses billed on it, against what they cost us (functions/expenses.php) $can_see_expenses = lookupUserPermission('module_financial') >= 1; $can_bill_expenses = $can_edit && $can_edit_lines && lookupUserPermission('module_financial') >= 2; $can_unbill_expenses = $can_edit && lookupUserPermission('module_financial') >= 2 && expenseCanUnbill($status); $billed_expenses = $can_see_expenses ? expenseOnInvoice($invoice_id) : []; $unbilled_expenses = $can_bill_expenses ? count(expenseUnbilled($client_id)) : 0; // Trips billed on it (functions/trips.php) - the driving out to the client $billed_trips = $can_see_expenses ? tripsOnInvoice($invoice_id) : []; $unbilled_trips = $can_bill_expenses ? count(tripUnbilled($client_id)) : 0; $can_unbill_trips = $can_edit && tripCanUnbill($status); $guest_url = billingGuestUrl('invoice', $invoice); // Hardware sold on it, and how much of it is on the client's assets (functions/products.php) $can_see_assets = lookupUserPermission('module_support') >= 1; $hardware = $can_see_assets ? productInvoiceHardware($invoice_id) : []; $hardware_units = array_sum(array_column($hardware, 'units')); $hardware_to_add = $status === 'Cancelled' ? 0 : array_sum(array_column($hardware, 'to_add')); $can_add_assets = $hardware_to_add > 0 && lookupUserPermission('module_support') >= 2; // Payment reminders - how many have gone, and when the next one goes (functions/billing_email.php) $owed = in_array($state['state'], ['open', 'overdue'], true) && $status !== 'Draft'; $reminder_rules = billingReminderRules(); $reminders_sent = $owed ? mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(*) AS sent, MAX(history_created_at) AS last FROM history WHERE history_invoice_id = $invoice_id AND (history_description LIKE 'Reminder emailed%' OR history_description LIKE 'Cron Emailed Overdue Invoice%')")) : null; $client_reminders = intval(getFieldById('clients', $client_id, 'client_reminders') ?? 1); $reminder_next = $owed && $client_reminders ? billingReminderNext($invoice, $reminder_rules, billingReminderAutopay($invoice)) : null; $csrf = $_SESSION['csrf_token']; // Made by a recurring invoice? $recurring = intval($invoice['invoice_recurring_invoice_id']) ? mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT recurring_invoice_id, recurring_invoice_prefix, recurring_invoice_number FROM recurring_invoices WHERE recurring_invoice_id = " . intval($invoice['invoice_recurring_invoice_id']))) : null; // Made from a quote? $from_quote = intval($invoice['invoice_quote_id'] ?? 0) ? mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT quote_id, quote_prefix, quote_number FROM quotes WHERE quote_id = " . intval($invoice['invoice_quote_id']))) : null; $progress = $state['paid'] > 0 && $totals['total'] > 0 ? min(100, round($state['paid'] / $totals['total'] * 100)) : 0; // Override Tab Title // No Sanitizing needed as this var will only be used in the tab title $tab_title = $invoice['client_name']; $page_title = $number; $paper = [ 'type' => 'invoice', 'row' => $invoice, 'items' => $items, 'totals' => $totals, 'paid' => $state['paid'], 'balance' => $state['balance'], 'edit' => $can_edit_lines, 'ai' => $can_edit_lines && aiReady('Billing'), 'notes_edit' => $can_edit, 'taxes' => $can_edit_lines ? billingTaxes($invoice['invoice_created_at']) : [], 'logo_url' => billingCompany()['logo_url'], 'csrf' => $csrf, ]; ?>

Invoice

From From Created

Payment

of
Paid
in ' . count($payments) . ' payment' . (count($payments) === 1 ? '' : 's') . '' : '' ?>
Due
Terms
Reminders
Off - set in Invoice Settings Off for Next - No more on the schedule
Margin
'invoice', 'doc_id' => $invoice_id]) : null; if ($reprice_doc && $reprice_doc['lines']) { ?>
Prices
line at an old price
Client
Not sent yet - the client can't see it

Payments

No payments yet.

Hardware

· sold
= $line['units']) { ?> On assets of
  • Archived (moved to another client)

Tickets

worked
unbilled ticket for could go on this invoice.

Expenses

Cost → line gone' ?>
expense to bill to could go on this invoice.

Travel

line gone' ?>
trip to bill to could go on this invoice.

History