Ordamo
All features
Who it's for
PricingBlog
EN
Log inSign up free

Changelog

What changed in Ordamo and when — the buttons that moved, the imports that learned a new file, and the plumbing underneath.

  1. The order page hears about its own order

    A store can now rewrite an order's money, status, customer and lines while you are looking at the page, and the page went on showing what was true when it opened — which read as a deposit that would not update. Going into Edit and back out was not clearing a cache, it was the page finally asking again. It watches its own order and lines now, so a change from the store arrives on its own.

    The three subscriptions that had been on that page for months — expenses, batches, income — had never fired either: subscribe() was called with no callback, which is where CHANNEL_ERROR and TIMED_OUT were going. The status is logged now.

  2. A discount taken in Shopify reaches the balance

    A merchant took 20 off an order in the store. The deposit followed it down, the lines did not, and the order page — which works the balance out from the lines — reported 20 still owed by somebody who owed nothing. Lines are reconciled against the store now, including a discount taken off the whole order rather than off one line.

    total_discount is the line's own discount and, by Shopify's own wording, excludes order-level ones; the line's share of those lives in discount_allocations, which the mapper never read.

  3. Correcting the buyer in Shopify corrects it here

    Changing the buyer on an order in the store left Ordamo pointing at the old customer, silently — the rule was protecting a name somebody had typed by hand, and in doing so ignored the ordinary case. It follows the store now. The same update had also started writing an email address into the place a name was: the connector could not tell a real name from the address it falls back to when a store gives none, so a named customer became their email on the next update. A real name always wins now.

  4. The connect link stops dying while you use it

    Pressing Connect in Shopify, then glancing back at the Shopify tab, was enough to invalidate the link in the tab you were about to sign in on — and the error blamed you for reusing it. A code that has not expired is reused rather than replaced.

  5. The lapsed-plan banner asks whether there is a plan now

    It told a merchant with a paid, active plan that their orders had stopped arriving. They had not: one order was refused during an afternoon of testing months of log-time ago, and the banner was reading the log rather than the plan. A record of what once happened is not a statement about what is happening. The plan is checked first now.

  6. A Shopify store puts its orders straight into a workspace

    Install the app from Shopify and paid orders arrive in Ordamo as they happen — the lines, the customer, the deposit and the balance — through the same code that reads an uploaded export. Linking a shop to a workspace starts on the app's own page inside Shopify, which hands you a one-time link to finish in a normal tab, because a Shopify admin cannot hold an Ordamo session. That page also says whether orders are actually arriving, and what stopped them when they are not.

    Managed installation, so there is no OAuth redirect: the embedded page trades its session token for an offline token and subscribes the shop to orders/create, orders/updated and app/uninstalled. Those subscriptions are now checked on every load rather than only when a token is minted — the first connected shop had a good token, no subscriptions, and nothing on screen saying so.

  7. One Shopify order stops becoming two Ordamo orders

    Marking a draft paid makes Shopify send two deliveries in the same moment. Both ran the whole intake, both read no order yet, and both wrote one — carrying the same number, in a merchant's books, with nothing complaining anywhere. The link is claimed before the order is written now, so one delivery wins and the other restates the order that is already there.

  8. Connecting a shop asks for a plan, and cancelling one stops new orders

    The free stretch is three orders entered by hand; a connected store is an endless supply of them, so the plan is asked for at the moment of connecting rather than per order — refusing an order a customer has already paid for is worse than saying no before anything is at stake. Cancelling afterwards stops new orders too. An order Ordamo already holds still updates, and the refusal is visible: the app's page says since when orders stopped, that they are still in Shopify, and where to start a plan.

  9. Nothing is stored until a European has said it may be

    Consent Mode v2 on the site. Nothing is written for a visitor in the EEA, the UK or Switzerland until they have answered, and our own events wait in memory rather than on disk while the question is open — released under the same id on a yes, dropped on a no. Outside those places nothing changed.

  10. Production can open an order again

    For anyone on the Production role the orders list showed the orders and every one of their pages said "Order not found". The page was asking for a view only the owner is allowed to read, so it got nothing back and drew the empty state. It asks for what Production can actually see.

  11. A paused plan is not an ended one

    Pausing a subscription made the billing screen announce that the plan had ended, naming a date more than a week away in the past tense — and the button beside it offered to start a second subscription next to the one that was only suspended. Paused reads as paused now, and the button goes to the billing portal, which is where a pause is lifted.

  12. Setting up is free; the wall moves to the moment a customer sees the order

    Clients, products, batches, costs, income and marking a balance paid no longer ask for a card. That is your own setup and nobody outside the workshop reads it. Three real orders come free with it, and the trial runs fourteen days. The card is for sending an order to a customer — including from the Send button on the orders list, which was the one route to that moment that never asked.

    The quota is a fourth fact in lib/paywall, not a fourth verdict: allow, ask and wait still, with a count that has not arrived answering "wait" rather than accusing somebody of spending a free stretch nobody had measured.

  13. The assistant is metered by the day, not once per account

    Three requests for the life of an account made the assistant something you tried and then never had again, which stopped making sense the moment the first three orders became free. It is a daily allowance now: three chats and nine messages a day without a plan, five and twenty-five with one. Chats are the number that counts, because a new one re-reads the workspace; a follow-up in a chat you already started today is not a new one. The counter also stopped sitting under the composer while you type — it appears when the day is actually spent.

  14. Saving something stops clearing your sample data behind your back

    The first real record you saved was firing a workspace-wide delete of the example ones as a side effect of pressing Save. It could not even succeed: an order entered against one of the sample customers — the obvious thing to do, they are in the dropdown — left a real row pointing at an example one, so the delete was refused and nothing said so. Clearing is a button on the banner now. It asks first, and it names what goes, because the payment methods and expense categories the sample created are the parts nobody pictures until they are gone.

  15. The sample workspace reads properly

    It was arriving with mangled characters in the names, and its settled orders were reading as money still owed. It makes furniture now, and the rows it seeds say what they mean. Workspaces seeded before the fix have been repaired in place.

  16. One broken rule stops cancelling everybody's recurring expenses

    For several nights no recurring expense posted anywhere. A rule left behind by a deleted account failed, and the nightly run was a single transaction, so every workspace's rules rolled back with it and nothing on screen said so. Each rule stands on its own now. One that fails keeps its due date, so the charge is deferred rather than lost, and the failure is written on the row and counted in the section's header — which is the part you can see while the section is collapsed. "Run now" bills your own rules straight away instead of waiting for the night.

    recurring_expenses.user_id never had the foreign key "Expenses".user_id has always had; it does now, and the orphans are gone. process_recurring_expenses() runs each rule in its own subtransaction. The nightly call stays service_role and "Run now" is the same loop, scoped to the caller's workspace.

  17. Correcting an order corrects the income behind it

    The two income records mirroring an order's deposit and balance were written when the order was created and never moved again. Fixing a deposit updated the order and left the ledger holding the old figure, so the order page reported two things at once: the deposit right, the balance due stale, and nothing saying they disagreed. An edit moves them now, and orders corrected before this went out have been caught up in place. A balance you marked paid by hand is left alone — a correction to a booking does not get to rewrite a receipt.

    An AFTER UPDATE trigger beside create_order_income, and a one-off backfill that moves a mirror only while it still holds what the insert trigger derived. Which leg a row belongs to is a column now rather than a string parsed out of the note.

  18. A batch's payments stop lying once they are edited

    The same hole on the production side. The expense written when you recorded a batch payment never followed a correction, so the batch knew what it had paid while the expense list, the dashboard total and anything exported to an accountant carried the first figure. The amount follows the batch now, which is the authority on its own payments. A payment date or a note you set yourself stays yours.

    A batch_payment column marks which leg a row mirrors, for the same reason the order side stopped reading the generated note.

  19. The assistant's other chats are reachable on a phone

    The list of chats was hidden on narrow screens and nothing replaced it, so the only chat you could open on a phone was the last one you had touched. Same list, in a sheet.

  20. A page that cannot load says so, instead of saying your account is empty

    When a list failed to load, four screens showed a message and then drew the first-run empty state underneath it — so a dropped connection read as an account with nothing in it, and invited you to create the records you already had. All seven list screens now say what could not be loaded, say nothing is lost, and offer Try again. The loading skeletons were rebuilt to the size of the rows they stand in for, so the page stops jumping when the data lands.

    The failure state replaces an empty screen, never a full one: react-query keeps the rows it already has when a background refetch fails, and blanking them to announce a blip would be the worse bug.

  21. A paid account stops being asked to buy a plan

    Pressing Send on an order could open the buy-a-plan dialog to someone already paying. The gate had one answer for "no plan" and for "the subscription has not come back yet", and it failed closed, so on the first press of a session it accused whoever was quickest. There are three answers now, and a press made while the answer is still in flight is held and goes through the moment it arrives.

  22. The confirmation link lands on sign in

    The link in the sign-up email dropped you on the marketing home page with nothing saying what had just happened — and on the occasions it did come back to the app, it skipped the sign-in screen entirely on whatever device opened the mail. It ends on sign in now, greeting the address it just confirmed.

  23. The same figure reads the same on every screen

    18,900 came out as $18.9K on the dashboard and $19K on expenses, because two different pieces of code were shortening money. One does it now, and it keeps the decimal even when it is zero, so an axis lines up. Percentages got the same rule: a 13.3% margin had been reading 13% on three of the dashboard's figures.

  24. The app stops animating itself in

    Every page faded and rose as it arrived, and every chart on the dashboard drew itself over a second and a half — long enough that a bar caught mid-animation looked like a bar clipped by a bug. Both are off. The dashboard keeps one entrance, the first time you open it in a browser session.

  25. The batch product list, and the two pickers in the order form

    The products inside a batch were a grid pretending to be a table, with a footer that lined up with none of the columns above it and five columns that crushed into each other on a phone. It is a table now, and it scrolls. In the order form, the customer picker shows the name, phone and email it searches by, and the product picker shows name, SKU and attributes, with the price right-aligned so prices compare down the column instead of sitting in chips of different widths. A product priced at zero no longer looks like one with no price at all.

  26. One way to save a setting, and an order can be edited from its own page

    The four settings forms ended four different ways: the button in three different places, under four different labels, on tabs that had already said which settings these were. One button now, in one place, at the end of the form — disabled until something has actually changed, with "Unsaved changes" beside it when it wakes up. Nothing autosaves, because a half-typed tax rate or a half-typed company name is not something to write down on your behalf. The order page also has an Edit action beside Send, so changing a price no longer means going back to the list.

  27. Nothing on screen is shouting

    Uppercase labels are gone — forty-six of them, from the dialogs, the customer's order page, the sign-in screen and the site. A label above a section stays a label by being small and quiet rather than by being set in capitals.

  28. The assistant reads before it asks you to pay

    The trial used to be asked for on the first message, so nothing had been read by the time the question arrived. Three requests per account are free now. The wall stands on Save instead, and it names what it is about to save — the order for the customer you just sent a screenshot of. Under the sample data, the block that asks for your own work leads with the screenshot and the store export. Importing a spreadsheet asks for the trial the same way every other save does.

    FREE_REQUESTS in the assistant-chat edge function, counted from ai_usage_log and answered with 402 AI_TRIAL_REQUIRED; the client mirrors the count so the number is on screen before it runs out. An order saved from a chat now completes the onboarding step and clears the seeded example rows, which only the manual forms did before.

  29. Mark the balance as paid from the order itself

    The button lived on the Income screen, which is not where you are when the transfer lands. It is on the order now: one press, and the balance updates on the order, on the customer and on the dashboard at once. The payment link on your customer's order page is clickable too, on the phone they are reading it from.

  30. An Etsy order export maps itself

    Download "Sold Order Items" from Etsy and import it — the columns match themselves the way a Shopify or Tiendanube export already did. "Buyer" is an Etsy handle rather than a person, so the customer's name comes from Ship Name. Etsy has no status words, so Date Paid and Date Shipped are read as the fact that it was paid and shipped. The "Sold Orders" file carries no line items and is not accepted.

  31. Pages stay on screen while the app loads

    Every page arrived, then blanked into a spinner, then came back. The static page now stays until the real one is ready and is taken away in the same frame it is replaced, so the comparison pages and the demo order open on their content.

    The prerendered markup is written into #prerender beside #root; the Suspense fallback is empty while it is on screen and PrerenderSweep removes it in a layout effect.

  32. What a production run cost goes back onto what it made

    A batch knows what you actually paid the workshop — the deposit, the balance, the extra invoice that arrived late. One button carries that onto the products the run produced and onto the open orders that were never costed, so the next order is priced against what you paid rather than what you guessed.

    Allocation is proportional to the estimates already on the lines; orders already carrying a production cost are left alone.

  33. The assistant moved to the pages where the data lives

    Instead of one chat to remember, there is a button beside the thing you are making: "Add from screenshot" next to New order, "Add from invoice" next to New batch, "Add from chat" next to New customer. Each opens with the job already typed. Import became a form rather than a conversation — pick what the file is, drop it, check the column table, press Import. Nothing is written until you confirm it.

    Known headers are matched from a dictionary first; one import-mapping call settles what spelling could not, and it is not counted as one of the day's chats.

  34. Send to Ordamo from the iPhone share sheet

    A screenshot of the chat where the order was agreed can go straight from the phone into Ordamo, and it is waiting as a thread with an unread mark when you get back to a desk. iPhone only: Safari has no share target, so it is a signed Shortcut that asks once for your key. The daily limit counts chats, not messages, so answering a question back is free.

Something here you want and cannot find, or something that broke? marat@ordamo.app.

Ordamo

Built for orders that take weeks to deliver

Who it's for
Ordamo vsall 21 compared →
marat@ordamo.app