Files
itflow/agent/modals/expense/expense_import_rules.php
johnnyq 53d0f8a841 Expenses stage 4: getting expenses in - Import Statement from the expenses menu brings a card or bank CSV in as expenses, reading lines before the header, commas, semicolons or tabs, Windows text and amounts like (12.00), 12.00 CR or 1.234,56, guessing the date and its format, description, memo, amount or money out and in columns, sign and reference and remembering them per account so the next statement goes straight to the review, matching each line to a vendor from what was picked for that merchant last time or a vendor name in the text (shortened names too) with its last category, suggesting a new vendor named from the line when nothing matches, locking lines imported before so a statement never comes in twice, leaving out lines that look entered by hand within 4 days and linking them, leaving out money in unless ticked, filling in the same merchant's other lines, bulk category and client and billing on, making new vendors once and opening the account's expenses for those dates, with remembered merchants to see or forget; paid personally expenses with who paid them that count as spent on their date but move no balance until paid back, a To reimburse pill with what each agent is owed, Reimburse paying back the ticked expenses from one account on one date as a Reimbursement in Transactions with undo for full financial access, quick look, list, vendor page, bulk, export and dashboard showing who paid and whether they were paid back, database 3.0.2 with expense_import_key, expense_paid_by, expense_reimbursement_id, expense_import_rules, reimbursements and account_import_map, CHANGELOG updated
2026-10-16 19:12:03 -04:00

75 lines
3.6 KiB
PHP

<?php
/*
* The merchants Import Statement remembers - what a line starting with
* these words was matched to last time: the vendor, category and client,
* and how often. Forgetting one has the next statement match it afresh.
*/
require_once '../../../includes/modal_header.php';
enforceUserPermission('module_financial', 2);
$rules = [];
$sql = mysqli_query($mysqli, "SELECT import_rule_id, import_rule_match, import_rule_used_count, import_rule_billable, vendor_name, category_name, client_name
FROM expense_import_rules
LEFT JOIN vendors ON vendor_id = import_rule_vendor_id
LEFT JOIN categories ON category_id = import_rule_category_id
LEFT JOIN clients ON client_id = import_rule_client_id
ORDER BY import_rule_used_count DESC, import_rule_match ASC LIMIT 500");
while ($row = mysqli_fetch_assoc($sql)) {
$rules[] = $row;
}
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-magic me-2"></i>Remembered Merchants <span class="fw-normal text-white-50 ms-1"><?= count($rules) ?></span></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body p-0">
<div class="px-3 py-2 small text-body-secondary border-bottom">A statement line whose words start like these is matched to what was picked for it last time. Each import updates them.</div>
<?php if ($rules) { ?>
<div class="table-responsive" style="max-height: 28rem;">
<table class="table table-sm table-hover align-middle mb-0 small">
<thead class="table-light text-nowrap">
<tr>
<th class="ps-3">Line starts</th>
<th>Vendor</th>
<th>Category</th>
<th>Client</th>
<th class="text-end">Used</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($rules as $rule) { ?>
<tr>
<td class="ps-3 font-monospace"><?= escapeHtml($rule['import_rule_match']) ?></td>
<td><?= escapeHtml($rule['vendor_name'] ?: 'A vendor since deleted') ?></td>
<td><?= escapeHtml($rule['category_name'] ?: '-') ?></td>
<td><?= escapeHtml($rule['client_name'] ?: '-') ?><?= intval($rule['import_rule_billable']) ? ' <span class="badge bg-warning-subtle text-warning-emphasis fw-normal">bill on</span>' : '' ?></td>
<td class="text-end"><?= intval($rule['import_rule_used_count']) ?></td>
<td class="text-end pe-3">
<a class="btn btn-sm btn-link text-danger p-0 confirm-link" title="Forget" href="post.php?expense_import_rule_delete=<?= intval($rule['import_rule_id']) ?>&amp;csrf_token=<?= $_SESSION['csrf_token'] ?>"
data-confirm-text="Lines starting &quot;<?= escapeHtml($rule['import_rule_match']) ?>&quot; are matched afresh next time."><i class="fas fa-fw fa-times"></i></a>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<?php } else { ?>
<div class="itflow-asset-empty">
<i class="fas fa-magic fa-2x mb-2 opacity-50"></i>
<div>Nothing remembered yet - each statement you import teaches it.</div>
</div>
<?php } ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><i class="fa fa-times me-2"></i>Close</button>
</div>
<?php
require_once '../../../includes/modal_footer.php';