Files
itflow/agent/post/revenue.php
johnnyq 11dabf8a26 Income modernized for MSP use: rebuilt Income list with cards for this month against the same days of last month, the year so far with a monthly average, recurring per month from running recurring invoices and still owed on invoices with the late part, pills for invoice payments, other income, paid online and no category, client/category/date filters with account and payment method under More filters, search by amount, reference and invoice number, footer total, sort whitelist and ?open=; new payment quick look with the invoice, paid in all and still owed, the other payments on it, online fee when recorded, Open Invoice, Email Receipt, Edit and Delete; new other income quick look with who entered it and what the client has paid in this year, with Edit, Copy and Delete; one New/Edit/Copy Other Income form with a client picker, an icon on every field, validation of every field and the currency taken from the account; other income now needs Financial write to add and change and Financial full to delete, payments keep their Sales and Financial rules; bulk Set Category (a payment's invoice takes it), Set Account, Set Payment Method, Set Client and Delete for other income, with payments left alone where they belong to their invoice; export with the list's filters plus Invoice and Paid Online columns; income counted the same everywhere through new functions/income.php, so uncategorised other income now counts on the dashboard, client overview, Income Summary, P&L, Income by Client and Client Profitability while transfers stay out; Income Summary and P&L No category rows and type links open the list, Transactions opens the quick looks, Accounts link to their transactions and income, search has an Income group; demo data adds quarterly rebates, interest and referral fees; income_model.php and the three old bulk modals removed; database 3.0.5 makes revenue_description text, adds revenue_created_by backfilled from the audit log and date keys on revenues and payments; CHANGELOG updated
2026-10-16 21:17:50 -04:00

94 lines
3.0 KiB
PHP

<?php
/*
* ITFlow - other income: money in that isn't for an invoice (revenues).
* New and Copy post add_revenue, Edit posts edit_revenue - both through
* incomeRevenueSave(), which checks every field. Write access to Financial
* adds and changes it; full access deletes it.
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
/** The form's fields as incomeRevenueSave() takes them. */
function revenuePostInput() {
return [
'date' => (string) ($_POST['date'] ?? ''),
'amount' => (string) ($_POST['amount'] ?? ''),
'account' => intval($_POST['account'] ?? 0),
'category' => intval($_POST['category'] ?? 0),
'client_id' => intval($_POST['client_id'] ?? 0),
'payment_method' => (string) ($_POST['payment_method'] ?? ''),
'reference' => (string) ($_POST['reference'] ?? ''),
'description' => (string) ($_POST['description'] ?? ''),
];
}
if (isset($_POST['add_revenue'])) {
validateCSRFToken();
enforceUserPermission('module_financial', 2);
$revenue_id = incomeRevenueSave(revenuePostInput(), 0, $error);
if (!$revenue_id) {
flashAlert(escapeHtml($error), 'error');
redirect();
}
$row = incomeRevenueRow($revenue_id);
$label = incomeRevenueLabel($row);
logAudit("Revenue", "Create", "$session_name added other income " . escapeSql($label), intval($row['revenue_client_id']), $revenue_id);
flashAlert("Income <strong>" . escapeHtml($label) . "</strong> added");
redirect();
}
if (isset($_POST['edit_revenue'])) {
validateCSRFToken();
enforceUserPermission('module_financial', 2);
$revenue_id = intval($_POST['revenue_id'] ?? 0);
$before = incomeRevenueRow($revenue_id);
if (!incomeRevenueSave(revenuePostInput(), $revenue_id, $error)) {
flashAlert(escapeHtml($error), 'error');
redirect();
}
$row = incomeRevenueRow($revenue_id);
$label = incomeRevenueLabel($row);
logAudit("Revenue", "Edit", "$session_name edited other income " . escapeSql($label), intval($row['revenue_client_id']), $revenue_id);
if ($before && intval($before['revenue_client_id']) && intval($before['revenue_client_id']) !== intval($row['revenue_client_id'])) {
logAudit("Revenue", "Edit", "$session_name moved other income " . escapeSql($label) . " to " . escapeSql($row['client_name'] ?: 'no client'), intval($before['revenue_client_id']), $revenue_id);
}
flashAlert("Income <strong>" . escapeHtml($label) . "</strong> saved");
redirect();
}
if (isset($_GET['delete_revenue'])) {
validateCSRFToken();
enforceUserPermission('module_financial', 3);
$row = incomeRevenueDelete(intval($_GET['delete_revenue']), $error);
if (!$row) {
flashAlert(escapeHtml($error), 'error');
redirect();
}
$label = incomeRevenueLabel($row);
logAudit("Revenue", "Delete", "$session_name deleted other income " . escapeSql($label), intval($row['revenue_client_id']));
flashAlert("Income <strong>" . escapeHtml($label) . "</strong> deleted", 'error');
redirect();
}