Settings > Invoices and billing - how invoices and recurring * invoices are numbered, what each invoice shows, late fees, who hears of one * paid online, payment reminders and statements (cron/nightly_tasks.php), * how ticket time, billable expenses and trips are billed, and what agents * are paid back for driving. Saved by edit_invoice_settings * (admin/post/settings_invoice.php). The sections the rest of ITFlow links * to keep their anchors - #reminders, #billing-time, #billable-expenses and * #mileage. */ require_once "includes/inc_all_admin.php"; $company = settingsCurrent(['company_tax_id'], 'companies'); $reminder_rules = billingReminderRules(); $reminder_before = implode(', ', array_reverse(array_map('abs', array_filter($reminder_rules['days'], function ($day) { return $day < 0; })))); $reminder_after = implode(', ', array_filter($reminder_rules['days'], function ($day) { return $day > 0; })); $reminder_on_due = settingsChecked('reminder_on_due', in_array(0, $reminder_rules['days'], true)); $time_rules = billingTimeRules(); $trip_rules = tripRules(); $statement_days = []; for ($day = 1; $day <= 28; $day++) { $statement_days[$day] = 'On the ' . $day . ([1 => 'st', 2 => 'nd', 3 => 'rd', 21 => 'st', 22 => 'nd', 23 => 'rd'][$day] ?? 'th'); } $decimal = function ($value, $places) { return $value > 0 ? rtrim(rtrim(number_format($value, $places, '.', ''), '0'), '.') : ''; }; echo settingsPageStart('invoice'); ?>
Invoices
Recurring invoices
5, 'maxlength' => 65000, 'help' => 'Plain text - each new line is kept. Payment terms, bank details, the late fee.']) ?> 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.']) ?>
Payment reminders are off, so no late fee is added.
'Say so in the footer above, so a client knows before it comes.']) ?>
'fa-percent', 'type' => 'number', 'min' => 0, 'max' => 100, 'step' => '0.01', 'label' => 'Each late fee', 'suffix' => '% of what is owed']) ?>
Payment providers.') ?>
'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.']) ?> 'However it is paid in full - online, by autopay or a payment you record. A ticket linked to the invoice that is On Hold opens again at the same time, and its agent is told.']) ?> 'settingsReminders']) ?>
'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.']) ?>
'fa-exclamation-circle', 'maxlength' => 120, 'label' => 'After it is due', 'suffix' => 'days late', 'placeholder' => 'None - or 7, 14, 30']) ?>
'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 . An invoice a recurring autopay charges on its due date isn't reminded before then.
'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.']) ?>
'fa-calendar-day', 'label' => 'Day of the month', 'search' => false]) ?>
'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.']) ?> Defaults when the client has none.', 'billing-time') ?>
'fa-stopwatch', 'label' => 'Round to']) ?>
'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']) ?>
'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.']) ?>
'fa-cube', 'maxlength' => 200, 'required' => true, 'label' => 'Invoice line', 'placeholder' => 'Support [Hourly]', 'help' => 'The ticket number, subject and date go in its description.']) ?>
'fa-percent', 'inputmode' => 'decimal', 'label' => 'Markup to start with', 'placeholder' => '0', 'suffix' => '%', 'help' => '0 bills it at cost. Each expense can have its own.']) ?>
'Miles', 'km' => 'Kilometers'], ['icon' => 'fa-ruler', 'help' => 'For every trip, the rates below and the reports. Distances already logged aren\'t converted.']) ?>
'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.']) ?>
'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
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.']) ?>
'fa-road', 'inputmode' => 'decimal', 'label' => 'Billed a ' . tripUnitOne(), 'placeholder' => '0.00', 'help' => 'For the whole trip, there and back.']) ?>
'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.']) ?>
'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.']) ?>
The price can be changed in Unbilled Time before it goes on.