= settingsSectionStart('numbering', 'Numbering', 'Each invoice gets the next number, after its prefix - one a recurring invoice makes too. Recurring invoices are numbered on their own.') ?>
Invoices
= settingsNumberingFields('invoice', $config_invoice_prefix, $config_invoice_next_number) ?>
Recurring invoices
= settingsNumberingFields('recurring_invoice', $config_recurring_invoice_prefix, $config_recurring_invoice_next_number) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('invoice', 'On the invoice', 'What every invoice shows - on the page, the PDF and the client portal.') ?>
= settingsTextarea('config_invoice_footer', $config_invoice_footer, ['rows' => 5, 'maxlength' => 65000, 'help' => 'Plain text - each new line is kept. Payment terms, bank details, the late fee.']) ?>
= settingsSwitch('config_invoice_show_tax_id', $config_invoice_show_tax_id, ['help' => trim((string) $company['company_tax_id']) !== ''
? 'Under your address - ' . escapeHtml($company['company_tax_id']) . ', from
Company details.'
: 'Under your address. There is none in
Company details yet.']) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('late-fees', 'Late fees', 'A percent of what is still owed, added as a line of its own every 30 days late - by the nightly job, while payment reminders are on.') ?>
Payment reminders are off, so no late fee is added.
= settingsSwitch('config_invoice_late_fee_enable', $config_invoice_late_fee_enable, ['help' => 'Say so in the footer above, so a client knows before it comes.']) ?>
= settingsInput('config_invoice_late_fee_percent', $decimal(floatval($config_invoice_late_fee_percent), 2) ?: '0', ['icon' => 'fa-percent', 'type' => 'number', 'min' => 0, 'max' => 100, 'step' => '0.01',
'label' => 'Each late fee', 'suffix' => '% of what is owed']) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('paid', 'Paid online', 'When a client pays an invoice by card - in the client portal or from the link in its email - through a provider in
Payment providers.') ?>
= paymentProviderSummaryHtml() ?>
= settingsInput('config_invoice_paid_notification_email', $config_invoice_paid_notification_email, ['icon' => 'fa-bell', 'type' => 'email', 'maxlength' => 200,
'placeholder' => 'billing@company.com', 'help' => 'A shared mailbox or list works best. Empty, nobody is emailed - the payment is still recorded.']) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('reminders', 'Reminders and statements', 'Reminders go to each client\'s primary and billing contacts while an invoice is still owed, with a button to view and pay it. A client can be left out of reminders and statements on the Billing tab of its Edit window.', 'reminders') ?>
= settingsSwitch('config_send_invoice_reminders', $reminder_rules['enabled'], ['id' => 'settingsReminders']) ?>
= settingsInput('reminder_before', $reminder_before, ['icon' => 'fa-hourglass-start', 'maxlength' => 60, 'label' => 'Before it is due', 'suffix' => 'days',
'placeholder' => 'None - or 3, or 3, 7', 'help' => 'Up to 60 days before.']) ?>
= settingsInput('reminder_after', $reminder_after, ['icon' => 'fa-exclamation-circle', 'maxlength' => 120, 'label' => 'After it is due', 'suffix' => 'days late',
'placeholder' => 'None - or 7, 14, 30']) ?>
= settingsInput('reminder_repeat', intval($reminder_rules['repeat']), ['icon' => 'fa-redo-alt', 'type' => 'number', 'min' => 0, 'max' => 365, 'label' => 'Then every',
'suffix' => 'days until paid', 'help' => '0 for no more after the last one.']) ?>
Reminders go = escapeHtml(billingReminderScheduleText($reminder_rules)) ?>. An invoice a recurring autopay charges on its due date isn't reminded before then.
= settingsSwitch('config_statement_monthly', $reminder_rules['statement_monthly'], ['id' => 'settingsStatements',
'label' => 'Email a statement each month to every client with a balance', 'help' => 'Their open invoices, how late each is and what is owed, as a PDF too.']) ?>
= settingsSelect('config_statement_day', $reminder_rules['statement_day'], $statement_days, ['icon' => 'fa-calendar-day', 'label' => 'Day of the month', 'search' => false]) ?>
= settingsSwitch('config_billing_email_attach_pdf', $reminder_rules['attach_pdf'], ['id' => 'settingsAttachPdf', 'label' => 'Attach the PDF to invoice, quote, reminder and statement emails',
'help' => 'The default in each Send window, and what reminders, statements and recurring invoices do.']) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('time', 'Billing time', 'How the time logged on a billable ticket becomes hours on an invoice - in Unbilled Time, a ticket\'s Invoice window and Add Tickets. Each ticket\'s time is rounded once, as a whole, and billed at the client\'s hourly rate, or the one in
Defaults when the client has none.', 'billing-time') ?>
= settingsSelect('config_time_increment', $time_rules['increment'], billingTimeIncrements(), ['icon' => 'fa-stopwatch', 'label' => 'Round to']) ?>
= settingsSelect('config_time_rounding', $time_rules['rounding'], ['nearest' => 'To the nearest - under half a step rounds down', 'up' => 'Always up - any part of a step bills the whole step'],
['icon' => 'fa-sort-amount-up']) ?>
= settingsSelect('config_time_minimum', $time_rules['minimum'], [0 => 'No minimum', 15 => '15 minutes', 30 => '30 minutes', 60 => '1 hour', 120 => '2 hours'],
['icon' => 'fa-arrow-down', 'help' => 'Once it has any time logged. A ticket with none bills nothing unless the hours are typed.']) ?>
= settingsInput('config_time_item_name', $time_rules['item_name'], ['icon' => 'fa-cube', 'maxlength' => 200, 'required' => true, 'label' => 'Invoice line',
'placeholder' => 'Support [Hourly]', 'help' => 'The ticket number, subject and date go in its description.']) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('expenses', 'Billable expenses', 'An expense for a client can be billed on to them - it waits in Unbilled Time and goes on their invoice at what it cost, less any refund, plus a markup. A recurring expense can be billed on each time it records one.', 'billable-expenses') ?>
= settingsInput('config_expense_markup', rtrim(rtrim(number_format(expenseMarkupDefault(), 2, '.', ''), '0'), '.'), ['icon' => 'fa-percent', 'inputmode' => 'decimal', 'label' => 'Markup to start with',
'placeholder' => '0', 'suffix' => '%', 'help' => '0 bills it at cost. Each expense can have its own.']) ?>
= settingsSectionEnd() ?>
= settingsSectionStart('mileage', 'Trips and mileage', 'An agent driving their own vehicle is paid back for the distance: Pay Mileage on the Trips page makes their trips a mileage expense they paid personally, to pay back with Reimburse. A trip for a client can be billed to them from Unbilled Time, beside their tickets and expenses.', 'mileage') ?>
= settingsSelect('config_mileage_unit', $trip_rules['unit'], ['mi' => 'Miles', 'km' => 'Kilometers'], ['icon' => 'fa-ruler',
'help' => 'For every trip, the rates below and the reports. Distances already logged aren\'t converted.']) ?>
= settingsInput('config_mileage_rate', $decimal($trip_rules['rate'], 4), ['icon' => 'fa-hand-holding-usd', 'inputmode' => 'decimal', 'label' => 'Paid back a ' . tripUnitOne(),
'placeholder' => '0.70', 'help' => 'For driving their own vehicle - your reimbursement rate, such as the IRS standard mileage rate. Empty turns paying back off.']) ?>
= settingsSelect('config_mileage_category_id', $trip_rules['category_id'], [], ['icon' => 'fa-list', 'search' => true,
'options_html' => '' . categoryOptionsHtml('Expense', intval(settingsValue('config_mileage_category_id', $trip_rules['category_id']))),
'append' => categoryAddButtonHtml('Expense', 'btn btn-secondary'),
'help' => 'The expense category of the mileage paid back. The expenses are to the vendor Mileage, made the first time.']) ?>
Billing trips
= settingsInput('config_trip_charge', $trip_rules['charge'] > 0 ? number_format($trip_rules['charge'], 2, '.', '') : '', ['icon' => 'fa-dollar-sign', 'inputmode' => 'decimal',
'placeholder' => '0.00', 'help' => 'What each billable trip bills to start with.']) ?>
= settingsInput('config_trip_bill_rate', $decimal($trip_rules['bill_rate'], 4), ['icon' => 'fa-road', 'inputmode' => 'decimal', 'label' => 'Billed a ' . tripUnitOne(),
'placeholder' => '0.00', 'help' => 'For the whole trip, there and back.']) ?>
= settingsInput('config_trip_included', $decimal($trip_rules['included'], 1), ['icon' => 'fa-route', 'inputmode' => 'decimal', 'label' => 'The charge covers the first',
'placeholder' => '0', 'suffix' => tripUnit(true), 'help' => 'The rate bills only the distance beyond it. Empty bills all of it.']) ?>
= settingsInput('config_trip_item_name', $trip_rules['item_name'], ['icon' => 'fa-cube', 'maxlength' => 200, 'required' => true, 'label' => 'Invoice line',
'placeholder' => 'Travel', 'help' => 'What it was for, the route, date and distance go in its description.']) ?>
= tripBillingOn() ? 'A trip bills ' . escapeHtml(tripBillRuleText()) . '.' : 'With no charge and no rate, trips aren\'t billed.' ?> The price can be changed in Unbilled Time before it goes on.
= settingsSectionEnd() ?>
= settingsSaveBar('edit_invoice_settings') ?>