What's New
A running list of notable changes and new features in Knowledge ERP.
This page tracks notable, user-facing changes to Knowledge ERP.
We're pre-1.0, so this is a running highlights list for the current (
0.x) line — entries are added as features ship. Once we cut official releases, this page becomes versioned release notes tied to each release.
Recent highlights #
You can rename your business #
The name you typed at sign-up used to be permanent — a typo, a rebrand or a change of trading name meant a support ticket. It is now a field on Account Settings → Branding, next to your logo, and saving it updates every place your customers see it: the portal, your public booking pages, document PDFs, and the sender name and subject line of the emails you send them.
Because it goes straight to your customers' inboxes, only your administrators can change it. Anyone else who can open Account Settings sees it greyed, with a note saying who to ask, and every rename is recorded in your change history with who did it and when.
Your web address does not move. Renaming changes what you are called, not the subdomain you sign in at, so nothing your customers have bookmarked breaks. Ask support if you want the subdomain changed too.
Three settings alongside it moved to administrators for the same reason — they are what your customers see, rather than how you work internally: your logo, your timezone (it decides the time shown on your booking page and in every confirmation email) and your portal support email (it is where customers are told to write). The portal welcome message and the two auto-label toggles are unchanged and still open to anyone with the manage settings permission, and so is the page itself — see Who can change what.
While we were in there: account settings changes are now recorded in your change history. They were not before, so a changed tolerance or a switched-off two-factor rule left no trace at all.
Moving a booking is now as careful as making one #
The public booking page promises "Nothing is booked until you press Confirm". Moving a booking did not keep that promise: the times on the reschedule page were submit buttons, so one click — one mis-click — silently moved a medical appointment, with no review and no way back.
Picking a time now opens a review step that states the time being given up, the time being taken, the clock both are on, and what pressing Confirm will actually do. A pending booking moves there and then, and the customer gets a fresh confirmation email with a calendar entry that replaces the old one; a confirmed booking that needs your approval is lodged as a request, and the screen says in so many words that the old time is still held until you answer. Either way your cancellation-notice address is emailed — a customer moving their own appointment used to change your diary with nothing at all to tell you.
The page itself was rebuilt to match the booking calendar: the same month-style grid, the same key, your opening hours, and a timezone control it never had. And it now asks your opening hours before it offers a day — it used to offer Saturday to a business that shuts at the weekend and then answer the click with "nothing free that day", which reads as somebody else got there first.
Every stated time says which clock it is on #
Following on from the timezone work in the last release: the staff emails (new booking, cancellation, reschedule request), the reminder text message and the customer portal all used to print a bare "2:00 PM". They now name the branch's zone — which matters most in the staff inbox, where a two-site business reads both sites' mail side by side.
Underneath, an appointment's time is now a moment on the branch's clock rather than on the server's. A site several hours from the server had bookings turn "past" at the wrong moment: one behind the server was telling customers an appointment could no longer be changed online while it was still that afternoon, and one ahead of it went on offering to move bookings it had already sat through.
Booking pages that answer a nervous customer's questions #
All from watching a first-time customer book an evening physiotherapy appointment:
- The notes box says who reads it. It names your business and says the answer is published nowhere. She had been asked about her shoulder by an anonymous text area and deliberately wrote less than she should have.
- "Before your visit." A new field on the appointment type — what to bring, when to arrive, whether a referral is needed, your cancellation policy — published on the confirmation screen, in the confirmation email and on the customer's own booking page. Blank publishes nothing; none of it is written for you.
- The link out of the confirmation is now "View, move or cancel this booking". It used to say "View or cancel", which hid the thing most people come back for behind the one they are afraid of.
- The calendar key names states, not colours. It read "Selectable / Amber / Grey" to a screen reader, and inside the grid the colour was the only difference between fully booked and closed. Both now carry a mark and a spoken label.
- The back arrow stops at this month. It used to walk into months that were entirely over, which reads as a broken calendar rather than as the past.
- A type with no price says so on its own page, so you are asked once rather than finding out from a customer who did not book. Publishing without a price on purpose is still perfectly allowed — the page has never guessed at one.
Permissions in plain English, and one fewer way to be surprised by them #
The role editor now names every permission after what it lets somebody do rather than after the database verb behind it — Write off damaged, lost or expired stock instead of Discard Units, See the list of Products and Open a Product instead of View Any Products and View Products. Inside each area they are grouped by the kind of authority they carry, with money and the irreversible ones together at the bottom where somebody looking for danger is looking. Switch on Show the technical permission names if you want the stored names back.
Three related changes ship with it:
- Every permission now has a checkbox. Approving purchase orders, delivering transfers, managing API keys, account settings and billing had none — the View Role page named them and the editor could not touch them.
- Take a permission away from one person. Alongside the extra permissions you could already grant, you can now remove one, for that person only, whatever their roles say. It applies everywhere: the app, the mobile app and any API key they own.
- A Surveys role. A tenant on the Surveys module had no role that could use it but Admin.
Each role also carries a line saying what it is for, shown beside it on the staff form — where you are choosing one, rather than a menu section away.
Invite a colleague instead of inventing their password #
Adding somebody now emails them a signed, single-use link on which they choose their own password. You never see it. Resend invitation on their row issues a fresh one, and the View User page says whether theirs has been accepted. Setting a password directly is still there for somebody with no email of their own.
The two spend limits on the staff form now have to be answered. They meant opposite things when left blank and blank was the default for both, so accepting the defaults handed a new hire unlimited authority to sign off other people's spending. Both also appear on the View User page. See Users, Roles & Permissions.
An empty list now says why it is empty #
A picker reading No options available and a Products list reading No products yet answered none of the questions a person actually has — does nothing match, do we have none, or am I not allowed? One tester with twenty-seven products narrowed the list and concluded she had deleted her catalogue.
Check Out a Unit now says which condition emptied it: no units on file at all, no Product marked Returnable, or Returnable stock that exists but is all in another status, named and counted. The Products list tells a filtered-empty list apart from an empty catalogue, says how many Products you still hold, and offers Clear filters. Neither is ever phrased as a permission problem, because neither is one.
The per-row Check Out on a unit that cannot go out is now greyed with the reason on it, instead of opening a modal whose entire content was a refusal.
Usage Type is a question again, not a default #
Only a Returnable Product can be checked out, loaned or rented, and new Products used to arrive pre-set to Consumable. A business building a tool catalogue therefore made a catalogue nothing could be lent from, and found out much later, with no field to go back and look at.
There is no default now. Picking a category still prefills the usage type that category mostly holds — that is inferred from your own catalogue. See Products.
The Reorder Queue shows the maximum it is filling to #
A minimum of 5 and one angle grinder on the shelf produced a suggestion of 49. That was right — the Product's Max Amount was 50 and the queue tops up to it — but neither the maximum nor the word appeared anywhere on the screen.
The queue now carries Min and Max columns, and each suggested quantity says which level it fills to. Raising a purchase order offers both readings — cover the shortfall and fill to the maximum — with the number on each. The queue also gained the CSV export the Low Stock Report used to hold alone, and each of the two screens now says which one it is and points at the other. See Reorder Suggestions.
Smaller things in the stockroom #
- Book in Stock is its own entry in the Inventory menu. Receiving was four clicks deep inside a single Product, and its save button said Create — which made one tester hesitate before every line of a twelve-item delivery.
- The unit picker names the bin a unit is in, so four identical tape measures can be told apart by the shelf rather than by a barcode you would have to scan to read.
- The Checkouts list showed Checked In: Active for kit that was still out. It reads Not yet.
- The Products list stopped showing Units and Quantity On Hand as the same number twice: the quantity column appears only where something in your catalogue is measured rather than counted.
A way back in when you have forgotten your password #
The sign-in page now has Forgot password?, which emails a link to choose a new one. Until now there was no self-service route at all — an administrator had to reset people by hand, which was awkward on its own and a genuine dead end once two-step sign-in became mandatory.
The link works once and expires in 15 minutes, and it does not skip your second factor: you set the new password, then sign in and are asked for your code as usual. Changing your password also ends every other session that was still signed in as you. See Security & Data Privacy.
The search box in these documents works properly too. It used to drop a query typed before the search index had finished loading and then say nothing at all, which read as "there is nothing written about this". It now says what it is doing, tells you when there are no matches, and can be driven with the arrow keys and Enter.
Goods in, and goods back, with somebody's name on them #
Booking a delivery in by hand is the only way stock arrives for a business without the purchasing module, and it could not say who the goods came from. Add Stock now asks for the vendor and the delivery note / packing slip number, and fills the vendor in for you when the product's Vendors tab lists exactly one supplier. Both land on every movement the delivery writes, so the Movement Log's Vendor and Reference columns are finally fillable.
The reason list has a Goods received entry too. It had Found, Missing, Opening balance, Damaged and Correction, none of which means "a delivery turned up", so booking one in meant picking a reason that wasn't true.
Coming back the other way: checking a unit in now records who was returning it, so the movement log answers who had that tool? on its own row, and the note typed into the check-in form is shown on the checkout as Return Notes, beside the Checkout Notes it went out with. The check-in bin was already defaulted to the bin the unit left from — the field now says so, instead of looking like a guess. See Units and Asset Checkout.
A checkout has to say when the kit comes back #
The due date on a checkout used to be optional, and a handover with no date was treated as open-ended — which meant it clashed with every future booking of that product and got refused, often for no real reason.
It is required now, everywhere a unit goes out: the unit page, the units list, bulk check-out, the scan station, the mobile app and the API. With a date in hand the system can tell a genuine clash from a routine handover, so a checkout that's back before a booking starts simply goes ahead. There's no default date — the person handing the equipment over enters the day they expect it back. Checkouts already recorded without one are left exactly as they are. See Asset Checkout.
The work order lifecycle now holds on the API too #
The edit form has always known that a draft work order cannot jump straight to completed. The API did not, so the same change was allowed or refused depending on which door it came through, and an integration could leave a work order in a state the shop floor could never have put it in.
The rule now belongs to the work order itself. PATCH /api/v1/manufacturing/work-orders/{id} refuses a status the order cannot reach
from where it is, with a 422 carrying the same message the form shows —
naming the statuses it can move to. Nothing else in a refused request is
saved, and sending the status an order already has is not a move and is still
accepted. Every legal move works exactly as before. See
Work Orders.
If you script against this endpoint, check that anything advancing a work
order walks the lifecycle one stage at a time; a call that skipped stages will
now come back 422 instead of quietly succeeding.
You choose what QuickBooks receives #
Connecting QuickBooks used to mean everything went: every customer and vendor, with their contact details, addresses and your notes, pushed to Intuit on creation and on every edit, with no way to stop it. Including people added automatically — somebody who books online or opens a portal link becomes a customer like any other.
The QuickBooks settings page now has a switch for each record type — Customers, Vendors, Customer Invoices, Vendor Bills, Inventory Adjustments — and they all start off, matching how WooCommerce and Shopify have always worked. Note that invoices need Customers switched on and bills need Vendors, since a document in QuickBooks has to name the party it belongs to. See QuickBooks.
The public booking page is more careful about what it confirms #
Type an address into a booking page and it would tell you whether that address held a booking — useful to the customer who forgot she had already booked, and useful to anybody working through a list of addresses.
That check is now much narrower and much harder to abuse. It matches only the address actually typed on the booking, for the same service, so a booking made under a different address is no longer mentioned. Attempts are rate-limited per address and per network, and recorded (hashed) so a sweep can be spotted.
Where having an appointment at all is private — a clinic, a therapist, anything health-related — you can now switch on Require email verification before booking for a location. The customer gets a six-digit code by email and the booking is taken once they enter it. Until then the page looks nothing up and says nothing, so it cannot be asked about anybody. It also stops someone booking in a stranger's name and having your confirmation land in their inbox. Off unless you turn it on. See Appointments.
An adjustment now says what kind of adjustment it was #
Most movements explain themselves: a Purchase came from a vendor, a Sale went to a customer. Adjustment was the exception — the type for a change with no document behind it — so the log said only that somebody had changed a number, which reads as fiddling rather than as work.
Adjustments now carry a reason: Found, Missing, Opening balance, Damaged or Correction. The movement log reads Adjustment — Opening balance, and you can filter and group by reason to see how much of your shrinkage is loss, how much is damage, and how much is simply mis-keying.
It's filled in for you wherever the action already knows the answer — marking a unit missing, finding it again, or posting a stock count, which labels each line by which way its variance went. You're only asked when the system can't know, and it stays optional. See Units.
An option for the customer whose need isn't on your list #
A booking page offered your services and nothing else, so a customer who didn't recognise their own problem in the list either guessed or gave up.
Any appointment type can now be marked a catch-all. It is listed after your real services under its own heading, and never asks the customer to choose equipment — nobody knows yet what the job needs. You write the name, so it fits what you actually do: "Something else", "Ask us for a quote", "General enquiry", "Diagnostic visit". Add as many as you like.
Alongside it, any type can replace the plain "Notes" label on the booking form with your own question — "Tell us what you need and we'll call you back", "Describe the fault". On a catch-all the answer is required, since it is the only thing that says what the appointment is for. See Appointment Types.
A customer statement adds up #
The totals across the top of a statement counted only issued invoices, while the list underneath them showed everything — including drafts you had not sent and invoices you had voided. A customer whose invoices were all still drafts got "$0 invoiced" printed above a list of invoices, and a voided invoice sat in the list looking owed while counting toward nothing.
The statement now reports one set of invoices throughout: the ones actually issued. Drafts and voided invoices are still on the customer's own Invoices tab, where they belong.
The trial email limit now counts people, not messages #
The cap on customer email during a trial used to count messages: 250 of them per 30 days. That number could not tell a business apart from a spammer, since 250 emails to your twenty regular customers and 250 emails to 250 strangers counted exactly the same — so it had to sit high enough not to interrupt ordinary work, which is precisely where it stopped catching the thing it was for.
A trial can now reach 100 different people per 30 days, with no limit on how many messages you send them. Emailing the same customer ten times counts once, so quoting, invoicing and confirming appointments with the customers you already work with never runs the number down. The Subscription page and Account & Billing both explain it in those terms.
Equipment availability no longer counts units that are not there #
The available figure on a loan or rental — the number a booking is taken against — counted every unit of a product, whatever state it was in. A unit that was missing, discarded, discontinued, in transit between locations, held for an order, or already checked out to somebody counted as available, so the system promised equipment and then refused to hand it over at the counter.
It now counts only what can actually be promised, and still books ahead correctly: a unit out on a loan that ends before your dates is counted, because it will be back. Nothing changed about how a booking is made — only that the number it is made against is now the truth.
The working screens ask for permission to work, not to read #
Ship, Receive (on purchase orders, transfers and customer returns), Approve, Match and the stock-count scanner used to open for anyone who could read the record. Each now needs the matching update permission, so a coordinator given read-only sales orders can follow an order's progress without being able to ship it. See Users, roles and permissions.
You may need to add an update permission to a role whose people do this work and only had view before.
Restoring a deleted user needs a free seat #
A deleted user does not count against your seat cap, so restoring one is now refused when every seat is taken — one at a time and in bulk alike — exactly as re-enabling a disabled user already was. Free a seat or add one first.
Rentals refuse consumable stock #
Renting something out promises its return, which consumable stock cannot make. A rental line whose product is marked Consumable is now rejected at reserve and pickup, in the app and over the API — the rule loans have always had. See Rental agreements.
A quote of nothing but free text no longer converts to an empty order #
A quote line does not need a product — you can quote "custom fabrication, $500" as wording alone — but a sales order line does, so those lines have nothing to carry across. A quote made up entirely of them used to convert to an order with nothing in it. It is now refused, with a message naming what was wrong, and the confirmation dialog says why each dropped line is being left behind. A quote with a mix converts as before. See Quotes.
Your orders now say which status is which #
The customer portal showed an order's two statuses as bare badges side by side — "Shipped" next to "Processing" — with nothing saying that they answer different questions. Both are now labelled, on the portal and on the order PDF. Same badges, same colours, same meaning; they just say what they report.
A converted quote is now read-only, and says what it became #
Converting a quote to a sales order used to leave the quote fully editable. Change a line on it afterwards and its total quietly rewrote itself while the sales order went on saying something else, with nothing anywhere reporting that the two disagreed — and the quote's PDF regenerated with the new figure.
A Converted quote is now the record of what the customer agreed to: its fields, its line items and the quote itself can no longer be changed or deleted, over the API as well as in the app. Its detail page names the sales order it became and links to it, and the Sales Order column in the quote list now links to the order rather than back to the quote. To change what the customer gets, change the sales order. See Quotes.
Email a quote or an invoice straight from the record #
You can now send a quote or a customer invoice to your customer without leaving Knowledge ERP. Email Quote and Email Invoice sit on the record's own page, attach the same PDF the Download PDF button produces, and send the mail branded as your business — your name and logo, with replies going to your support address.
The address is filled in for you and always shown before anything is sent: for a quote, the contact named on it, otherwise the customer's own address. You can correct it. If there is no address on file, the button still opens, names the customer, and links to the record where you can add one — instead of leaving you with a dead button and no explanation.
This also closes a gap that had been quietly costing people trust: Mark as Sent changed a status and sent nothing, so a quote could read Sent having never left the building. Sending is now what marks a document as sent, and Mark as Sent says out loud that it only records a status, for documents you sent some other way.
Sends run in the background and report back — you get an in-app notification when the mail has actually gone out, or one explaining why it could not. An address that has hard-bounced or reported spam is refused before anything is sent, which protects delivery rates for everyone. Every send is recorded on the document's change log and on the customer's email history, so did we send it, when, and to whom is always answerable.
Sending is gated by a new Email sales documents permission, separate from editing
— a coordinator can be allowed to send documents without being allowed to change
them. It is granted to the default Sales and Bookkeeper roles. Both actions are
scriptable too: POST /api/v1/quotes/{id}/email and
POST /api/v1/customer-invoices/{id}/email. See
Quotes and Customer Invoices.
A rental with no rate is refused instead of invoiced at $0 #
A rental line whose Product had no matching Rental Rate used to fall back to a price of zero without saying so. The agreement would reserve, go out, come back, and close — and the customer invoice came to $0. Nobody was told. It happened whenever a rate was missing for the line's period, switched off, or never configured for that Product, and it also caught rentals started from a confirmed appointment.
A line's rate can now be genuinely blank, meaning nobody has priced this yet, and that is refused at every point where it would cost you money: reserving, picking up, and raising the invoice at close, including unattended cycle billing. The message names the product and the period that is missing. Fix the rate and press Pick Up again — the rate is re-snapshotted on the retry, so there is nothing to unwind.
A rate of 0 still works. Free-of-charge use, goodwill, a warranty loaner you bill as a rental purely for tracking — type 0 on the line and the whole lifecycle runs, invoicing at $0. Zero is a decision; blank is an oversight. A rate you typed is never overwritten by a rate added to the catalogue later.
Existing rental lines keep the 0 they were stored with and are treated as deliberately free — nothing was rewritten under you. The line item table now shows an unpriced line as Not priced rather than as $0.00.
The mobile app now refuses a unit that isn't in stock #
Checking a unit out from the mobile app had no status check at all. A unit that was already checked out to someone else, on hold for a sales order, in transit between locations, out of stock or discontinued would go out anyway — the app returned success and wrote a second checkout record. The desktop scan station refused the same unit, so the two doors disagreed, and the mobile one is the door warehouse staff actually use.
There is now one rule, applied everywhere a unit can be handed out: the unit page, the scan station, bulk check out, the mobile app, the rental endpoints and offline sync. A unit goes out only while it is In Stock, and a refusal names the status and the one thing that clears it instead of failing generically. Nothing is written when a checkout is refused.
Scan Checkout also stopped dropping units silently: if a unit's status changes between the scan and the confirm, it's named in the message and left in the list rather than quietly disappearing from the batch. See Asset Checkout.
Cancelling an appointment over the API gives the equipment back #
Cancelling an appointment in the app releases the units the booking was holding, so they go straight back on the shelf. Doing the same thing over the REST API did not — it wrote the status and left the units On Hold for an appointment nobody was attending, where nothing would free them but finding each one by hand. The API now runs the same release the Cancel and Mark No Show actions do. See Appointments.
The same endpoint also used to accept any text at all as a status, and answered
with a server error rather than a validation message. It — along with the work
order status and the customer- and vendor-return reason — now rejects an unknown
value with a 422 naming the field.
Locations are now reachable from the Appointments menu #
Everything that governs online booking — the public booking link, the opening hours, the appointment types and capacity — lives on a location, but Locations only appeared under Inventory. People setting up booking had no reason to look under stock control, and didn't find it.
Locations now also appears under Appointments as Appointments → Locations. It is the same list of the same records, not a second copy: the Appointments entry simply shows only the locations you have made bookable, and swaps the sales-order column for the counts of Appointment Types and Opening Hours on each — the two things a location needs before its booking link leads anywhere bookable. Inventory → Locations is unchanged and still lists every site.
Each menu entry highlights independently, so the sidebar always shows which door you came in by.
The Users list can now answer "who still works here?" #
Auditing who has access used to mean opening every user in turn, and the list could not tell you whether somebody who left still had a way in. It now shows:
- Status — Active or Disabled, with a filter, and a disabled row greyed back so it reads at a glance.
- Last sign-in — sortable, so dormant accounts sort to the top. Somebody who has never signed in reads Never, which is a different problem from a seat that has gone quiet.
Disable on a user's row revokes access properly rather than cosmetically: the app (including a session already open), the mobile app's password and QR sign-ins, and every API token they own. Their password, roles, permissions, tokens, records and history are all kept, so Enable puts them straight back to work. You cannot disable yourself, or the last active user who can manage users — both would lock the account out of the screen that undoes it.
The old Type: Person column is gone from most accounts. It was there to mark service accounts, so it now appears only when the account actually has one, and reads Can sign in rather than Type.
A disabled user frees their seat, so disabling somebody who has left lets you hire into that seat without buying another. Re-enabling someone therefore needs a free seat: if they are all taken, Enable is refused and tells you to disable somebody else or add seats. Neither changes what you are charged — freeing a seat moves the cap on who may sign in, not your subscription.
The REST API reports is_active, is_service_account and last_login_at on
each user. See
Users, Roles & Permissions.
Seats now show how many you're actually using #
The Subscription page used to state a bare seat count — "Seats: 25" — which told you what you were paying for but not whether anyone was in those seats. It now reads "4 of 10 in use", plus a line saying how many seats are paid for and idle, or that they're all taken. The same figure appears next to the seat stepper on Change plan, where you're deciding how many to buy, and at the top of the New user form, so running out of seats stops being a surprise. The count is the one the seat check itself uses, so it can never offer room that adding a user then refuses. See Subscription & Billing.
Every screen now has a ? that opens its guide #
The manual was only findable if you already knew to search for it — testers kept
telling us they'd stumbled on it by accident, or never at all. Now the header of
almost every screen carries a ? button linking to the guide for that exact
screen, and the user menu carries a permanent Help & documentation link. Both
open in a new tab, so nothing you were part-way through is lost. The home
dashboard's ? goes to the Quick Start, which is
where a first day is best spent. Screens we haven't written a guide for yet show
no button rather than a dead link.
Build a whole quote on one form #
Creating a quote used to take two stages: save a header with a customer and a date, get redirected, and only then add what you were actually quoting. Every quote began life at $0.00, and the ones people abandoned half-way stayed in the list looking indistinguishable from a real quote for nothing.
Line items are now on the create form, so a quote is one save from start to finish. The Product picker shows your catalogue as soon as you open it rather than waiting for you to guess a search term, and the line list refreshes properly after Create & create another — it used to show one line however many you added. The quote list gained a Lines column, amber at zero, so an unfinished quote is obvious at a glance.
Convert to SO is now Convert to Sales Order, and it is refused on a quote that would produce an empty order — one with no lines at all, or one whose lines are all returnable equipment, which conversion leaves behind because that gear goes out on a loan or a rental rather than a sale. The refusal says which case it is. A quote priced entirely at $0 still converts: zero is a legitimate price and only an empty order is refused.
The same live-total behaviour purchase orders already had now applies to sales orders, so the total updates as you add lines instead of after a reload. See Quotes.
Checkout, loan and rental, explained where you choose between them #
Three words for one idea — a unit leaving the building — with nothing on any screen saying which to use. A warehouse clerk in usability testing picked one essentially at random.
They are not three alternatives. A checkout is the movement record written every time a unit leaves the shelf; a loan and a rental are agreements that wrap one. So the choice is really two questions: does this need paperwork, and are you charging for it? A direct checkout is the quick path with neither — someone takes a unit and brings it back. A loan adds an agreement with a due date and no charge. A rental adds an agreement that bills.
That explanation now appears where the decision is actually made — on the check-out dialog itself, on the create pages, and on the empty states — rather than in a guide you would have to already know to look for. Two real gaps closed along the way: the unit page's check-out dialog had no due-date field at all, so anything handed out from there could never show up as overdue; and On Loan and On Rent offered only New Unit, with no way to start the agreement the page was named for. The Loans section is now Loan Agreements, since a section header inside a section called Loans was what people skipped past.
One thing worth knowing: a direct checkout's due date is a promise to bring it back, not a reservation. It does not hold the unit against a future loan or rental the way an agreement does. See Asset Checkout.
Cycle Counts are now Stock Counts #
Same feature, plainer name. Cycle counting, in the systems that use the phrase, is a schedule — a rolling policy for which shelves get counted this week. What you create here is one count of one location or bin, whenever you want it, so it is now called a Stock Count in the navigation, on the page and in the API reference.
Nothing else moved. The URLs, the database, the cycle_counts permission on your
roles and the /api/v1/inventory/cycle-counts endpoints all keep the old word, so
existing bookmarks, roles and integrations are unaffected. The manual still lists
"cycle count" as a synonym, and searching for it in the app's top bar takes you to
the same guide.
"Post Adjustments" is now "Finish Count & Update Stock" #
A warehouse clerk in usability testing read post as publish and wouldn't press
the button, because nothing told him whether it would put something on a
noticeboard or change stock. The button on a stock
count now says Finish Count & Update Stock. The
status it produces is still Posted and the API route is still
/cycle-counts/{id}/post — only the button changed.
Its confirmation used to say the action "cannot be undone" while a Delete button sat next to it, which read as a contradiction. It now says what is actually true: your counted quantities become the new stock levels, blank lines are left alone, the count locks, and deleting it afterwards does not put the old stock levels back. A wrong number is fixed by counting again or adjusting the unit — a new change on top, not an undo.
The appointments day sheet now shows double-bookings #
The appointments dashboard was a list you could read and nothing else. It is now the front desk's day sheet: rows grouped under dated day headings and ordered by start time, each showing the start and end time, a click-to-call phone number, and a link straight through to the booking. There is a New appointment button on it.
Most importantly, it flags clashes. When the same employee is booked for two appointments that overlap, both rows are marked Double-booked and a banner counts them for the period — the app already knew how to work this out and no screen had ever asked it. The same flag now appears as a Clash column on the Appointments list and on each appointment's page, naming who the conflict is with. Back-to-back bookings are not clashes, and a cancelled appointment releases its slot.
The Appointments list also now sorts by date and time by default. It sorted by date alone, so everything booked on the same day came back in the order it had been entered.
Booking an appointment from the staff side offers real times #
The Time field on the staff booking form is now a list of genuinely available slots — the times the location is open, long enough for the appointment to finish before closing, with an employee free. It is the same availability the public booking page offers, so a phone booking and a web booking can no longer disagree. Switch on Enter a time manually to type a time instead; the existing guards and the Book anyway override are unchanged.
Choosing a Customer now fills in their name, email and phone. It used to leave them blank, which meant re-typing an address you already had on file — and getting it wrong sent the confirmation somewhere the customer would never see it.
Cancel, not delete #
Appointment rows offered Delete next to View and Edit. They now offer Cancel, which is the real-world action: the status changes, held equipment is released, and the record and its history survive. Delete has moved into the row's More menu.
Relatedly, a cancelled appointment now refuses to send a feedback survey — asking someone how their appointment went when it never happened — and says why rather than quietly declining. The refusal holds at the point the email would go out, so an invitation queued before the appointment was cancelled is caught too.
Opening hours: the whole week on one screen #
Setting up a location's hours meant creating one record per day, and a day with no record was indistinguishable from a day you are closed. Both refused bookings and the calendar drew them identically.
Appointments → Opening Hours → Edit weekly hours now shows all seven days at
once, each set to Open, Closed or Not configured — so an unfinished
weekend reads as a gap rather than a decision. Holiday and seasonal date-range
rules are unaffected. The feature is called Opening Hours throughout now; it
had been Location Hours in the navigation and opening hours in every message
the app writes. The API still serves these from /api/v1/location-hours.
Reschedule Requests is now Customer Reschedule Requests, because it is an inbox of requests customers have sent in, not the place to reschedule something yourself.
Survey questions can branch, without typing a database key #
Conditional questions were technically supported and practically unusable: the survey builder asked for a Condition Question UUID in a free-text box, and on a new survey there were no UUIDs to type yet, so branching was impossible to set up at the point you'd actually want it. Nothing read the setting on the public page either, so a "conditional" question was shown to everyone — and if it was marked required, it silently blocked the submit button for people it was never meant for.
Both rules are now built from dropdowns, on a brand-new survey as readily as a saved one. Show only when hides a question until an earlier answer calls for it; Require an answer only when makes a question compulsory only in the cases that warrant it. Choose the earlier question from a list, choose is answered, is not answered, is or is not, and where a value is needed, choose it from that question's own answers rather than typing one.
The rules are enforced when the response is saved, not just in the browser: a question that was hidden is never stored as if it had been asked and never blocks a submission, and a conditionally required question is genuinely required once its condition is met. Required questions are now enforced on submission generally — previously a response could be submitted with them all blank.
A question can only depend on one above it, which also rules out two questions depending on each other. Moving a question above something it depends on, or deleting a question others depend on, is refused with an explanation rather than quietly rewriting the survey. See Customer Surveys.
Two related fixes came out of the same work: dragging questions into a new order never actually saved that order, and a new survey couldn't be saved at all without first filling in or deleting an automated trigger it opened with.
The Subscription page explains what ending your trial early actually does #
Start subscription now sat on the Subscription page with nothing to say why anyone would press it. The page now spells out the trade-off: a trial already includes your full plan, seats, modules and API access, so the only thing that changes is outbound customer email — capped at 250 messages per 30 days on a trial, with stricter spam-complaint limits, and uncapped once you're paying. It's also explicit that you forfeit the free days you have left, and that if you aren't sending much customer email there's no reason to end the trial early. See Account & Billing.
Customer-facing pages are yours, and surveys say what they're about #
Usability testing put a purchasing contact — a customer of one of our tenants, arriving on a magic link with no account and no idea what Knowledge ERP is — through the portal and a feedback survey. He judged everything he saw as coming from his supplier, which is exactly right, and it exposed several places where we broke that.
- Nothing customer-facing links to the staff sign-in any more. "Back to Knowledge ERP" on an error page took a buyer to our login form, which then offered him a trial of an ERP. Errors reached from the portal, a survey link, the booking pages or an emailed questionnaire are now branded as the tenant and point back at that tenant's customer portal.
- Your contact details are on every page. The account's portal support email and the location's support phone and address now appear in the footer of the portal, the survey pages and public booking — the same tenant identity that already brands outgoing email. The privacy notice, which used to end at "contact that business directly", now names the business and how to reach it.
- Surveys say which order they're about. A survey sent from a sales order, appointment or unit checkout shows that record — number, date and what was on it — at the top of the page. Optional questions are labelled Optional, and the thank-you page is now a receipt: the answers just given, the record they were about, and a reference to quote.
- Sign-in links are rate-limited, and the page says so. Repeated requests used to silently do nothing, so people kept pressing. Three links per address per fifteen minutes, with a message that reads the same whether or not the address is one of your customers.
See Customer Portal and Customer Surveys.
The public booking page now explains itself #
Testing it with someone who had never seen the product — no account, just a link — turned up a page that asked for a commitment without saying much of anything.
- Appointment types can carry a description and a note about cost, both shown on the booking page and on the new review screen. A name and a duration was all a customer used to get: "Equipment Loan" was read as a money loan. Neither field invents anything — leave the cost blank and the page stays silent. See Appointment Types.
- A review step before Confirm. Four numbered steps, the chosen type, day and time held on screen throughout, and a full summary before anything is written. It was previously possible to create a booking straight off the equipment list.
- The calendar tells "fully booked" from "closed" — they rendered as the same struck-through grey number, and they mean opposite things. There is now a key, and the location's opening hours are printed under the calendar.
- The equipment list is searchable, says "n in stock now" rather than an unqualified "n available", and has a box for the item that isn't listed.
Customers can see and cancel a booking they made without an account #
The public booking page used to end in a dead end: a reference number with nowhere to type it, and a booking link that reopened as a blank form. Someone who wasn't sure her booking had saved had no way to check, and no way to cancel it if it had.
The confirmation screen and the confirmation email now both carry a View or cancel this booking link to a "Your booking" page — what, where, when, status, reference, and a cancel button. Alongside it:
- The same person can no longer book the same slot twice. A second attempt says the first one saved, instead of creating a duplicate, and can email the details to the address that booked. A different customer taking the same slot is unaffected.
- Where to turn up is on the page. The location's address and phone number appear in the booking header, on the confirmation and in the email — and when a location has no address, the page says so instead of offering the location's name as a destination. Enabling appointments on a location now requires its address and support phone.
- Email addresses are validated properly, so
name@examplewith no.comis refused, and the reason is shown on the page rather than in a browser tooltip.
See Appointments & Scheduling.
Creating a role no longer starts from 400 empty checkboxes #
The role editor opened on ten collapsed sections and several hundred permissions, with no way to search them and no way to copy a role you already had. It now has:
- a search box over every permission at once — type
invoice, or an action likedelete, and only the matches stay on screen. Searching changes what you see, never what is ticked; - Expand all / Collapse all;
- Start from an existing role on the create form, which ticks that role's permissions for you to edit; and
- Duplicate on a role's row in the Roles list, which copies it outright under a new name.
It also stops offering permissions for modules that are not on your plan — with one exception: if a role already grants something in a module you have since dropped, that section still appears, with a note explaining why, so you can see and clear it rather than have it silently disappear.
A fix worth knowing about if you have edited roles. Saving a role used to rewrite its entire permission set from the checkboxes on screen, which quietly removed the few authorities that have no checkbox — approving purchase orders and bill variances, delivering transfers, managing API tokens, account settings and billing. So renaming the Bookkeeper role, for instance, silently cost it access to billing and account settings. Editing a role now leaves untouched anything the editor did not show you. If you edited a default role and someone lost an approval or settings authority, re-create it by duplicating a role that still has it, or ask support. See Users, Roles & Permissions.
Units of Measure is now clearly distinct from Units #
The navigation showed Units under Inventory and Units Of Measure under Account Administration, and the role editor listed "Inventory Units" and "Units" as separate permission groups — no way to tell which was which. The measurement catalogue is now consistently Units of Measure everywhere, including in the permission list; Units always means physical stock.
Global search now covers the records you transact on #
The search box at the top of every page used to reach only Products and Units, so looking up a customer by name came back empty. It now searches customers, vendors, sales orders, quotes, customer invoices, customer returns, purchase orders, vendor invoices, vendor returns, rental agreements, loan agreements and work orders — and documents match on the counterparty's name as well as their own number, so typing a customer's name brings back their orders, invoices and agreements next to the customer record. Each result carries a line of detail (who it's for, its status, the amount or date) so you can pick the right one without opening it. See Finding Records.
SKUs are now Products, and Items are now Units #
Usability testing kept catching people out on the old naming, so the catalogue record is now called a Product and the tracked physical record is a Unit: a Product is the catalogue entry; a Unit is one tracked item of it. A Product's unit-of-measure field is now labelled Unit of Measure.
Nothing moved — but the REST API was renamed to match, so there is no
UI-vs-API mismatch. Products are served from /api/v1/inventory/products and
referenced as product_id; Units from /api/v1/inventory/units and referenced
as unit_id; and the measurement catalogue moved from /api/v1/inventory/units
to /api/v1/inventory/units-of-measure to free that path up. SKU now means
what it means everywhere else — the identifier code on a Product, including the
supplier's own number on a Vendor SKU link.
Upgrading a script? Rename the paths above, and swap the payload fields
sku_id→product_idanditem_id→unit_id. Database columns and table names are unchanged.
A full self-service customer portal #
The customer portal grew from a read-only window into a real self-service area. Customers sign in passwordlessly and can now accept or decline quotes, pay invoices, request returns on shipped orders, reschedule, cancel, and edit appointments (including the requested equipment), and request due-date extensions on rentals and loans — all from clickable detail pages, with PDFs viewable in the browser. Tabs appear based on the account's modules or the customer's records, so prior history stays visible even if a module is later dropped. Every portal change is recorded in the change history as the customer.
Account branding on the portal, emails, and PDFs #
Upload an account logo under Account Settings → Branding. It now appears on the portal, in the emails the portal sends, and as a letterhead on every document PDF (quotes, invoices, sales orders, rental/loan agreements, returns, purchase orders) — alongside the issuing location's address, phone, and email.
Appointment rescheduling & approvals #
Customers can reschedule a pending appointment to any open slot themselves; a confirmed appointment becomes a reschedule request for staff to approve in a Filament queue — or applies immediately when the location turns on auto-approval. See Appointments.
Due-date reminders & extensions for rentals and loans #
Rentals and loans now email borrowers a due-date reminder before they're due (per a per-location lead time) and let customers request an extension from the portal — auto-applied or staff-approved per location. Rental extensions show an estimated added cost and bill through the normal rental cycle, so no separate invoice is created.
Configurable quote validity #
A new quote's "Valid Until" date now pre-fills from a per-location default (Location → Sales). Leave the location setting blank for quotes that never expire. See Quotes.
Sales orders: separate delivery status #
A sales order's status is now split into a clean lifecycle (Draft → Confirmed → Processing → Closed, or Cancelled) and an independent delivery status (New → Picking → Packed → Shipped → Delivered) you can filter on separately. Billing is derived from the order's invoices, and an order closes automatically once they're paid in full. See Sales Orders.
Equipment Loans #
Loan equipment to a customer at no charge — reserve it, check it out, and get it back — with the same availability and due-date tracking as rentals, minus the billing. Lives in the Inventory module (no Rentals subscription required). See Equipment Loans.
Shared customer directory #
Customer and contact records are now reachable from any customer-facing module (Inventory, Appointments, Rentals, Sales) — so you no longer need the Sales module just to keep customers. Sales transactions and the CRM pipeline stay under Sales. See Customers.
Smarter reorder suggestions #
Reorder suggestions now offer a second, trend-aware demand forecast method alongside the usage-and-lead-time baseline, shown side by side so you can compare — all computed on-server, no external service. See Smart Reorder Suggestions.
Sales orders: equipment vs. consumable #
Reusable equipment no longer goes out through sales orders — it's loaned or rented instead — and the Product usage type was renamed to the clearer Consumable / Returnable. Existing data is unaffected. See Sales Orders & Invoicing.
Documentation site #
This documentation site launched — public and searchable, organized by module, versioned, with links into the API reference. Start at the Quick Start.
Looking for the full history? #
Day-to-day changes are tracked in the project's version control. This page focuses on the changes that affect how you use the product.