40 Commits

Author SHA1 Message Date
johnnyq
1e5bffff3c Rates, net terms and SLAs come from the client's contract, else the instance defaults: database 3.5.0 adds a default after-hours rate (Settings > Defaults, now Rates and terms), gives each client whose own rate, net terms or SLAs differ from the defaults an active Standard terms contract setting just those (12-month term renewing itself, starting the day the client was added or the day before its earliest contract, archived with an archived client), deletes per-client SLA assignments and drops clients.client_rate and client_net_terms; time bills at the contract's rate, its after-hours rate or the default after-hours rate, else the default rate, new invoices are due on the contract's net terms else the default, and new tickets get the contract's SLA else the default; a client's own terms still apply until the update runs; the client add and edit windows lose the rate, terms and SLA fields for a note saying what the client is billed on and where it comes from, the Clients list loses Set Hourly Rate and Set Net Terms and shows the contract's rate, the overview's Terms shows the after-hours rate and whether terms are a contract's or the defaults, a contract's page and document show what it leaves empty from another contract in force or the default so signed documents stay unchanged, contract windows show the defaults as placeholders, contract names take a proper possessive; the client import and API create make a Standard terms contract for a rate or terms that aren't the defaults (returning contract_id), API update reports them in not_kept; the client export gives the rates, terms and SLAs as billed; demo data puts each demo client's terms on a contract; changelog updated 2026-10-27 22:22:34 -04:00
johnnyq
77df925981 Contracts stage 4: a contract in force sets the client's SLA for new tickets, the hourly rate with an after-hours rate for tickets opened outside business hours, and net terms for new invoices, the one that started last first and the client's own where it is empty; Unbilled Time bills each ticket at its own rate with one line per rate, and the ticket invoice window, Add Tickets, quote from a ticket, Unbilled Work and Time Detail reports, New Invoice, copy, quote to invoice, the invoice page, client overview and client edit follow it; a recurring invoice made from or linked to a contract is paused while it is a draft, started when it is made active or renewed with missed runs skipped, and paused once when it ends or its cancellation takes effect; new functions/contract_billing.php; fixes agent names double-escaped in the prepaid hours history; DB 3.4.5 adds contract_recurring_invoice_id and contract_recurring_stopped_at and treats a 0.00 contract rate as empty 2026-10-25 01:06:59 -04:00
johnnyq
bf89a86ab1 Categories stage 3: list category filters offer only the categories their records have through categoryFilterOptionsHtml, archived ones marked (archived) and referrals that aren't categories marked (not set up), on expenses, recurring expenses, income, invoices, products, tickets, recurring tickets, client referrals and their export windows; new filters for quotes and recurring invoices by category, assets by status, licenses by software type and racks by type, each also in its export window and filter summary; asset type tabs count within the chosen status, and license tabs within software type and license type, fixing license counts that ignored the license type filter; Category export column for invoices, quotes and recurring invoices and Status column for assets, off until ticked; lists and quick looks show a category as its icon in its color through categoryMarkHtml, or its dot without one, on expenses, recurring expenses, income, transactions, tickets, recurring tickets and the ticket page; Admin > Categories usage counts link to the new filtered lists; read-only categories API at api/v1/categories/read.php with kind, id, name, archived and paging, checked per kind against the module that uses it, with usage counts for keys whose user sees every client; racks Archived button kept on one line; changelog updated 2026-10-17 20:42:29 -04:00
johnnyq
87c441b3b9 Billing stage 5: payment reminders on a schedule set in Invoice Settings (days before, on and after the due date, then every N days until paid, with a client opt-out on the Billing tab and no reminder for autopay invoices until late), Send Reminder and next-reminder status on the invoice page, a message and PDF attachment in the invoice, quote and statement Send windows, a statement PDF with aging and an optional monthly statement run, a new look for invoice, quote, reminder, receipt, statement and team notice emails sent to primary and billing contacts, late fee added as a proper invoice line, fixes for the quote answered notice link and batch payment receipts, database 2.9.8 and changelog 2026-10-16 17:12:10 -04:00
johnnyq
2fcdd6006b Invoices, quotes and recurring invoices makeover stage 4: quote lines billed one time or each month, quarter or year with a Billed choice on the add-a-line row and in Edit Line, quotes grouped into One-time, Each month, Each quarter and Each year with a total for each on the page, PDF and client view, lines dragged within their own group, Start Billing on accepted quotes putting one-time lines on a draft invoice due on the client's terms and each recurring part on a new recurring invoice from a chosen date, emailed or left as drafts, or added to one of the client's recurring invoices of the same frequency, with an option to bill the first period on the invoice, an Invoiced as card on the quote linking every invoice and recurring invoice it became including ones it added lines to, From links back on invoices and recurring invoices, monthly amounts in the quotes list and its totals, search, client portal, quote email, Send and Copy windows, quotes export and client export, and Quotes Pipeline valuing quotes at up front plus a year of recurring lines. Fixes Make Invoice invoicing a quote twice or one never accepted, and its audit entry using the current quote prefix instead of the quote's own. Adds DB 2.9.3 with item_frequency, quote_monthly_amount, invoice_quote_id and recurring_invoice_quote_id, linking invoices to their quotes from history, quoteConvert() as the one invoicing path claiming the quote in a transaction, quoteLineGroups(), quoteAmountText() and quoteMadeFrom(), reportCsv() totals written as given, and updates the 26.11 changelog 2026-10-16 14:14:53 -04:00
johnnyq
fee0a5cb80 Invoices, quotes and recurring invoices makeover stage 1: one shared document page for all three with inline line editing (product pick, live line totals, drag to reorder, lines locked once paid or answered), shared New/Edit form, late recurring invoices offer to skip to the next date without billing missed runs, Add Payment shows remaining balance and account balances, Batch Payment lists the invoices it will pay, Add Tickets takes several at once, new PDF layout for invoices, quotes and packing slips with pay/answer QR codes and paid/answered stamps, Letter or A4 by country, guest invoice Pay Now with other open invoices, guest quote Accept/Decline then signed copy or PO upload. Line amounts rounded to the cent on save, expired quotes can no longer be accepted from the link, Batch Payment skips non-billable invoices, recurring list creation-date filter removed. Fixes discount reset to zero on invoice/quote edit, stock not moving on invoice item quantity change, invoice status not updating on payment edit, autopay left behind on recurring invoice delete. Consolidates line items, totals, statuses and PDFs into functions/billing.php, includes/billing_paper.php, agent/post/billing.php and functions/billing_pdf.php with a single billing_items_order ajax reorder; removes the three item edit modals, link_invoice_to_ticket, guest_quote_upload_file_modal.php and js/product_autocomplete.js 2026-10-16 12:37:50 -04:00
johnnyq
234afd25fb Contacts overhaul: rebuilt contacts list with role tabs and counts, avatars, flag pills, hover copy on phone/mobile/email, inline location picker, linked asset/credential/license/ticket chips and tag filter; contact page rebuilt to match the asset page with header actions, Reach/Details/Quick notes cards and tabbed Assets, Credentials, Tickets, Recurring, Licenses, Documents, Files, Services and Notes; add and edit contact share one tabbed form (Details, Roles, Access, Notes) with field icons, role switches, password generator, duplicate email check and photo removal; contact quick look redone to match the asset quick look; contact avatars now used everywhere a contact appears - contact pickers, ticket header, contact card, client replies, ticket list, kanban, assets, clients list, client header, overview key contacts, credentials, documents, services, invoice/quote/statement recipients, license users and global search - with each contact keeping the same colour throughout; ticket contact pickers show the name with title and role underneath; fixes: permission checks on the add contact modal and contact page/list actions, contact location limited to the contact's own client on add/edit/bulk assign, contacts list no longer selects user account columns, archived assets and credentials left off the contact page and quick look, saving a contact with the client portal disabled no longer clears their portal login method, replacing a photo no longer tries to delete a directory, sort column whitelisted, list counts and tags batched instead of per row, recurring ticket menu markup, undefined index notices, contacts list no longer scrolls sideways on phones, Edit Service shows avatars on unselected contacts and assets, license user labels toggle their checkbox; new functions/contact.php helpers (contactAvatar, contactLink, contactFlagPills, contactPhoneLink, contactAvatarData, contactOptionDescription), shared contact_form.php, contact_location quick pick, removed unused assetContactAvatar and clientOverviewPersonInitials 2026-10-14 18:33:18 -04:00
johnnyq
69484a8a2e Replace Tom Select with ITFlow's own select picker: native select stays the source of truth, search, checklists for multi selects, add-your-own for tag fields, phone sheet, and client/agent/contact avatars, tag and category colours, priority dots and asset icons in the options 2026-10-13 12:41:29 -04:00
johnnyq
9bfd26d57b Add titles to icon-only buttons
- title on 294 icon-only buttons, named for what each one does
- aria-label on the 7 show-password buttons (title becomes the popover
  header) and the portal mobile nav toggle
- Fix dead add-category button on products filter, credential bulk tag
  button now preselects Credential, drop duplicate inner-icon titles
2026-10-08 17:12:21 -04:00
johnnyq
86ba041cdc Add Quick Send Quote / Invoice to replicate the old single click to Send Email 2026-08-28 14:40:25 -04:00
johnnyq
68b15ca49b Email Invoice Only shows Billing and Primary, Quote shows Important Billing, Primary and Technical contacts that can be selected 2026-08-28 13:43:51 -04:00
johnnyq
72e6f23e19 Send Email and Mark Sent modals for invoices and quotes (db 2.7.7)
Send Email opens a contact picker instead of hardcoding the primary contact; Mark Sent asks how it went out and takes a note. Both log recipients / method / note to the document history. Handlers moved GET -> POST.

Fixes two pre-existing bugs in the email path: archived contacts were still receiving billing copies, and every copy was addressed to the primary contact by name.
2026-08-28 13:31:22 -04:00
johnnyq
8c0e5246b4 Fix Card Margin bottoms client header and ticket cards on the right 2026-08-14 19:08:15 -04:00
johnnyq
dc6b191eed Update Font, Migrated away from JQUERY dependent libs: toastr to bootstrap5 toasts, daterangepicker to flatpickr, select2 to Tom Select, InputMask to IMask 2026-08-14 17:08:40 -04:00
johnnyq
a084e37c39 Initial migration from AdminLTE 3 to 4, bootstrap 4 to 5 2026-08-14 13:22:11 -04:00
johnnyq
b3744e9ed5 More sweeps to replace select * with actual returned column names dramatically reduces php memory usage and speeds up processing dramatically especially in the crons since they run all the time 2026-08-06 13:10:23 -04:00
johnnyq
b8c9d5b4cf Query Optimization: Select only needed columns instead of SELECT * on looped queries 2026-08-06 12:59:43 -04:00
johnnyq
ddd9c2b56a clientScopeSql sweep whicn now removed the extra unessesary client joins 2026-08-06 11:45:56 -04:00
johnnyq
3c8f812a16 Feature: On all export modals added Filter Tab and Selectable Columns tab with default selected, also you can now export to a PDF 2026-07-30 00:46:15 -04:00
johnnyq
b3f959ac55 Use Short echo tags across the code 2026-07-28 18:47:52 -04:00
johnnyq
761b2a7af4 Module permissions modal enforcement sweep to match its post counterpart 2026-07-25 00:28:42 -04:00
johnnyq
2c09ce097c More Client Enforcement in modals across the app 2026-07-16 13:10:02 -04:00
johnnyq
7bc47a58fe Replace Function nullable_htmlentities() with just escapeHtml() and update all instances throughout 2026-07-14 17:10:45 -04:00
johnnyq
d2026a417f Add Client to top of the modals trips, ticket, recurring ticket, invoice, recurring invoice, quote and rework the UI for Ticket/Recurring ticket create Put Billable beside subject so it doesnt take up a whole row 2026-07-09 18:50:31 -04:00
johnnyq
fc59481476 Enforce Client Access in client selectbox 2026-07-09 16:17:00 -04:00
johnnyq
317fe91359 Add Missing clientEnforcement in various modals, already handled on POST also add client selection in edit trip and enforce client permissions on trips 2026-07-09 16:07:54 -04:00
johnnyq
065e674a68 Quotes: Fix Quote Copy missing client 2026-04-04 17:38:12 -04:00
johnnyq
6122efc870 Updated all Queries related to invoice items to reflect their new tables quote, invoice, recurring invoice items 2026-03-07 19:35:44 -05:00
johnnyq
6d2cb0aea3 Split out item edits into seperate posts and modals for editing invoice, quote and recurring invoice items 2026-03-07 12:12:27 -05:00
johnnyq
6f0a2a5a73 quotes: enforceClientAccess 2026-03-06 18:11:35 -05:00
johnnyq
2c47001b19 Quote: Add missing CSRF checks and missing permission on export quote pdf 2026-03-01 22:02:43 -05:00
johnnyq
0a30300bde replace all instances of mysqli_fetch_array with mysqli_fetch_assoc for better performance and memory usage 2026-01-14 17:30:23 -05:00
johnnyq
e1a579387f Convert all Import / Export Modals to Ajax and a few other lingering modals that were not converted yet 2025-12-02 15:04:05 -05:00
johnnyq
faa94d888d Convert Quote to Invoice to use ajax-modal 2025-11-28 14:44:47 -05:00
johnnyq
99e2487d2b Fix dupe race condition with ticket, invoice, quote, project, recurring ticket numbering when being created in parallel Atomically update and get the next ticket number in one SQL query everywhere. 2025-11-28 14:14:46 -05:00
johnnyq
ba2d6b6709 Convert Bulk Edit Product Category modal to ajax 2025-11-27 13:41:53 -05:00
johnnyq
a388a279bc Convert Bulk Edit Product Category modal to ajax 2025-11-27 13:40:09 -05:00
johnnyq
c851e54e1d Fix Decimal not showing on the iphone for specific fields associated to price cost percentage etc 2025-11-26 13:54:24 -05:00
johnnyq
41f9a2e6e2 Migrated add revenue, trip, quote, invoice, recurring invoice, product, document, folder, file, project, and asset interface over to the new ajax-modal 2025-11-03 14:06:44 -05:00
johnnyq
edabc5c33f rename /user/ to /agent/ and update links to use agent/ instead 2025-09-23 18:04:23 -04:00