There is a particular kind of dread that comes with replacing software that has run your business for 15 years. Every edge case, every workaround, every piece of institutional knowledge is baked into that system. And now you have to pull it out and put something new in its place, live, across 100 stores, without missing a beat.
Serialized product tracking. Distributed fulfillment. Cross-store allocation. Tier-based loyalty. Historical data migration. All running simultaneously across 100 live retail locations.
Here is how it was done.
The retailer had built something most retailers never manage: a custom system that genuinely fit their business. The problem was not that it stopped working. The problem was that it stopped growing.
Over 15 years, every new requirement had been bolted on. The codebase had become a single developer's institutional knowledge. No updates, no security roadmap, no way to add what a modern retail operation demands.
Fine until it is not, and catastrophic when it goes. Replacing it was not a software project. It was a controlled reconstruction of an entire operating model, built to run without interruption inside a live, high-volume retail business.
Serialized product sales, store-to-store transfers, ecommerce fulfillment, complex loyalty logic, EDI receiving, and millions of historical transactions — all controlled by a system that could no longer be updated, secured, or extended.
Developer lock-in. No innovation. Old code, old infrastructure, no security roadmap. Nothing could be added without breaking something else.
Erply had to take over every inventory movement across 100 stores in real time, integrate cleanly with NetSuite as the corporate ERP, and keep five years of historical sales data fully operational at the point of sale.
Not archived. Not locked in a legacy lookup tool. Right there in the checkout flow, behaving exactly like a transaction made yesterday.
In a business like this, inventory is not a number in a spreadsheet. It is the difference between fulfilling a cross-store order and sending a customer home empty-handed.
The system was built so that nothing moves physically without being reflected digitally.
When a product sells, inventory drops immediately. When it comes back, the cashier selects a reason code.
That reason code determines whether the item returns to sellable stock or routes to a non-sellable bin. No exceptions, no manual overrides.
Transfers between stores move through virtual staging bins and only register at the receiving location once physically confirmed.
Inventory cannot appear in two places at once. Reconciliation issues between locations are eliminated by design.
Receiving against a purchase order only adds inventory after quantities are verified. Shortages, over-receipts, and damaged goods are flagged before stock is added.
What is received physically matches what is recorded financially in NetSuite.
One of the more complex workflows the retailer runs is the cross-store order: a customer wants something the local store does not have, and the staff need to find it, commit to the sale, and fulfill it from wherever it exists in the network.
The old process relied on phone calls and manual coordination. The new one is entirely governed by the system.
When a cashier creates a sales order for an out-of-stock item, Erply checks inventory across all locations. If the company has none anywhere, the order is blocked. If stock exists elsewhere, the order requires full payment before submission, then routes automatically to the right fulfillment location.
A single order can split across multiple stores. The fulfilling store processes it through the WMS. Inventory deducts only when shipped. The selling store never touches the stock count.
The retailer's ecommerce operation does not run from a central warehouse. It runs from its stores. Every web order is routed, picked, packed, and shipped from a retail location, with the discipline of a single warehouse operation.
When a web order comes in, a best-store routing logic evaluates inventory availability, store priority, and location rules, then assigns the order to the optimal location. If a single store cannot fulfill the whole order, it splits automatically across multiple stores — each receiving its assigned portion.
An allocated order appears in a pick queue on a handheld device. Staff scan items, validate SKUs and serial numbers, and flag anything missing. Missing items trigger a reassignment to another location and a new routing decision.
At packing, box dimensions and weight are captured. ShipEngine generates the shipping label. Payment is validated through NetSuite before the shipment is finalized. If payment fails, the label does not print and the order remains unfulfilled.
Once shipped, inventory reduces and order status updates automatically across the store, ERP, and shipping system. No manual coordination. No gaps between what happened and what was recorded.
One of the most technically demanding parts of the project was historical data. The requirement was not to archive it. It was to make it fully operational inside the new system.
From the store team's perspective, there is no line between old data and new data. There is just the system.
A cashier searching for a three-year-old receipt can find it by customer, date, store, product, or serial number. A return against a historical transaction validates the remaining eligible quantity, preserves the original pricing and tax logic, and behaves identically to a return on a sale made yesterday.
Behind that experience is a data retrieval layer built specifically to handle queries at scale, with complete line-item detail and the identifiers required for returns and reporting.
Not a simple points accumulator. A tiered system with real economics, embedded directly into every transaction across stores and ecommerce.
Three tiers. Different earn rates. Automatic upgrades. Cross-channel redemption. Returns that recalculate everything.
This is the part of a retail platform that rarely gets talked about in product demos. But it is what separates a system that runs cleanly from one that quietly leaks margin every day.
Discount limits enforced by employee group, not by memory
Manager-level access required for certain refund types and tenders
Gift card returns validate against NetSuite before processing
Cash operations are permission-based. Voids controlled before day close.
Defective returns routed to RMA bins, reviewed, and written off through an approval process
Eleven distinct systems, all running simultaneously, across 100 live retail locations, from day one.
Specific SKUs are flagged as serialized. When selling more than one of the same SKU, each serial number must be captured individually. A sale cannot complete without valid serial entries.
On return, the system validates the serial against the original sale. If the serial is not found in historical data, the return is blocked. This prevents fraudulent returns and protects warranty integrity.
Employees pick orders using handheld devices. Items are scanned, validated, and moved from showroom into ecommerce staging bins. Missing items are flagged and inventory adjustments are recorded automatically.
Inventory does not deduct until packing is complete. Status updates trigger invoice creation and sync across all systems. Multi-box shipments are tracked at the line-item level.
Employees scan Box IDs tied to purchase orders, receiving entire contents in one step. If no Box ID is available, items are scanned individually against the purchase order.
The system flags shortages, over-receipts, and damaged goods before inventory is added. Discrepancies are documented and synced to NetSuite. What is received physically matches what is recorded financially.
When a return is processed with a defective reason code, the item is automatically routed to an RMA bin and physically separated from sellable inventory.
On a scheduled review cycle, items are evaluated and either restored to stock or written off through an approval process. Write-offs synchronize to NetSuite so financial inventory reflects operational reality.
During packing, the shipping address is validated, a request is sent to ShipEngine, and the best rate is retrieved. The label is generated and tracking is stored at the box and line-item level.
The credit card is charged at fulfillment. If payment fails, the label does not print, the order remains unfulfilled, and the customer is notified. Orders auto-cancel after three days if unresolved.
Physical gift cards and reward certificates operate on separate logic. Balances are created via API, validated at tender, and recorded in NetSuite. Retry logic handles API timeouts up to five attempts.
Points earn at different rates per tier. Thresholds generate reward certificates automatically. On return, points are deducted, tiers recalculate, and balances can go negative. Everything is governed by rules, not manual adjustment.
The system that came out the other side is not a collection of integrations holding hands. From the moment a customer walks into a store to the moment that transaction closes in the ERP, everything is connected, governed, and accurate. That is what it looks like when a retail platform is actually built for the weight of the business it runs.