In short
Perfect Pet is a pet products wholesaler near Athens. Its trade customers log in to a B2B shop we built, and every one of them can see a different price for the same product, which can change again as the quantity in the cart goes up. The prices come from Entersoft every night. This year we added an AI sales assistant to the same shop, and it had to quote exactly the same number the cart would charge. This is how the pricing works and what we learned from putting it in two places. The project overview is in the Perfect Pet case study.
Where the prices come from
Entersoft owns the truth. Every night at 03:00 the shop loads the ERP price lists into a single table, one row per catalogue, SKU and minimum quantity, with columns for price, promotional price, sale price and a percentage discount. The table is emptied and refilled in chunks of 500 rows, which keeps memory flat and means a half-finished load is obvious rather than subtly wrong.
Customers are loaded from Entersoft too, at 04:00, and each one is assigned a price catalogue there, not in the shop. The shop never invents a price. It only decides which of the ERP's numbers applies.
The four rules
For a given customer, product and quantity, the price is resolved in a fixed order:
1. product-level B2B price (the starting point) 2. customer's catalogue row with the (quantity tiers, e.g. 1+, 12+, 48+) highest from_quantity <= cart qty 3. discount on that row, first match: percentage -> sale price -> promo price 4. per-product extra charges (up to three, shown as separate lines)
The order matters more than any single rule. A percentage discount and a sale price on the same row must not stack, and a customer with no catalogue row must still see a sensible B2B price rather than the retail one.
Quantity tiers are re-applied every time the cart changes. Add two more boxes, cross a tier and every line recalculates. The extra charges are kept as separate line items rather than folded into the unit price, so the customer sees exactly what each charge is for.
The ERP decides who can buy, and how
The customer import does more than create logins. A parent account in Entersoft becomes one web login, and its child accounts become extra delivery addresses on it, each carrying its own customer and site code. When an order goes back to the ERP it lands against the right store, not just the right company.
The ERP status field locks and unlocks the web account, and the payment methods each customer may use (cash on delivery or bank transfer) come from the ERP as well. The sales team manages all of this where they already work, in Entersoft.
Then the AI assistant needed a price
This year we added an AI sales assistant to the shop, built on our Tec-AI platform. It talks to the shop through a set of tools, and one of the first questions a trade customer asks is "how much is this for me if I take 24?"
The cart's price logic lives inside the shop's session and cart code. The assistant has no cart and no session; it has a customer id and a question. So the rules had to be rebuilt as a stateless database query keyed by customer, following exactly the same four steps in the same order.
That's duplicated business logic, and duplicated logic drifts. We didn't pretend otherwise. The pricing class for the assistant opens with a comment saying that if the cart's pricing function changes, this one must change too. It's the honest version of the trade-off: extracting a shared pricing service would have meant rewriting the cart, and the cart works.
Orders go back to Entersoft, and the email waits
Orders are sent to Entersoft as trade documents, and the ERP's document code is stored on the order. Failed sends are queued, the admins are emailed, and an hourly job retries until four attempts have failed. Order statuses and tracking come back three times a day, and customers only get an email when a status has really changed.
Perfect Pet asked for one more rule: a customer should not receive an order confirmation until Entersoft has actually accepted the order. The confirmation email is now held until the ERP document number exists, released the moment the order is saved with it, with an hourly sweep for anything that slipped past. There is no timeout that sends it anyway. That was the client's call, and it's the right one for a wholesaler whose customers treat the confirmation as a commitment.
What we'd pass on
- Let the ERP own prices, customers and credit, and keep the shop's job to choosing the right ERP number. Every rule you copy into the shop is a rule that can disagree.
- Write the resolution order down as a numbered list the client can read and agree to. Most pricing disputes are about order, not amounts.
- When a second channel (an app, an AI assistant, a price feed) needs the same price, either share the code or say loudly in the code that you didn't.
Building B2B ordering on top of Entersoft or another ERP? See our B2B portal development and Entersoft integration work, or get in touch.