Test: Team38 OMS: The Retail System That Knows the Shelf, Not Just the Store

A clean Go and React monorepo for inventory, transfers, and purchase orders, built around one smart idea: retail software should point a worker to the exact location of an item.

6 to 8 min read View on GitHub More from lock44

A retail stockroom shown as a nested physical map, with a worker standing at the edge of the space and paths narrowing from store to zone to shelf. The image explains that this OMS is built to locate inventory at the level where a person can actually walk to it.
The repo’s core idea is spatial precision. Inventory is not just counted, it is addressed.
Key Takeaways

Why in stock is not enough

Most inventory systems stop at the wrong abstraction. They can tell you that a SKU exists in a store, but not whether it is in the back room, on the sales floor, or on shelf B2. That gap is where time gets wasted, and it is the gap this OMS tries to close.

The interesting thing about lock44/Test is that it treats retail as a physical search problem. The software is not just counting T-shirts. It is helping someone find the one they need, fast.

A staged transfer shown as a physical relay between two points, with a box marked pending on one side and the same box arriving at a new shelf marked done on the other. The image explains that stock movement is modeled as a process, not a single database update.
Movements are treated like real work. They start staged, then finish in a new physical location.

The hierarchy that makes the system useful

The schema is the heart of the repo. Instead of flattening everything into a store-level count, it builds a hierarchy: store, zone, location, inventory. That is a small design choice with a big consequence. It gives every item an address.

A store becomes navigable when zones and locations are first-class objects. The point is not only to know what exists, but where it lives.

Simple inventory appTeam38 OMS
Store, product, quantityStore, zone, location, product, quantity
Answers what is in stockAnswers where the item physically sits
Good for countsGood for finding and picking
One flat view of inventoryA map of actionable places

That contrast is the article in miniature. One model counts inventory. The other helps a worker move through space.

Transfers are modeled like real work

The movement workflow is more than CRUD. In the backend, a transfer is created in PENDING, then executed into DONE. That mirrors how operations actually work: plan first, move second, confirm after the physical step is complete.

// Conceptual shape of the movement flow
movement := CreateMovement{
    ProductID: 42,
    FromLocationID: 7,
    ToLocationID: 12,
    Status: "PENDING",
}

// Later, after the pick and move happen
ExecuteMovement(movement.ID)
// status becomes DONE

That staged model matters because it keeps the software honest. A transfer is not complete when the record is written. It is complete when the item is in the new place.

A Go backend without framework drag

The backend keeps to the Go standard library, using native HTTP routing instead of a heavier web framework. That choice keeps the service small, but it also forces discipline. Handlers do one job, migrations define the schema, and CORS is handled explicitly instead of hidden behind middleware magic.

Design choiceWhat it buys
net/http routingLess framework overhead and clearer request flow
golang-migrateSchema changes stay versioned and repeatable
Manual CORS handlingCross-origin behavior stays explicit
Dockerized PostgresThe local setup matches the app’s assumptions

This is not minimalism for its own sake. It is a practical backend shape for a team that wants control over behavior without dragging in a large dependency stack.

The frontend behaves like a purpose-built tool

The React app does not lean on a generic routing setup. Instead, it uses a custom page state model that passes navigation context forward, including the path back to where the user came from. That makes the UI feel closer to an internal operations console than a public website.

export type Page =
  | { name: 'dashboard' }
  | { name: 'location-items'; storeId: number; locationId: number }
  | { name: 'item-detail'; itemId: number; from: Page }

That shape is a strong fit for warehouse and store workflows. People are not browsing. They are drilling down, checking one thing, then returning to the previous view with context intact.

Design-first, even before every handler is finished

The repo feels professional because the contract came first. OpenAPI defines the shape of the system, Swagger UI makes it inspectable, and the folder structure cleanly separates backend, frontend, API docs, and reports. Even where some handlers still return mocked data, the boundaries are already in place.

Prototype habitThis repo’s habit
Build screens first, define data laterDefine the contract, then wire behavior
Let the UI drift from the APIKeep OpenAPI and the app aligned
Hide progress in ad hoc notesDocument structure in repo-level artifacts
Ship a demo shellShip an MVP scaffold that can harden over time

That is the real maturity signal here. The system already has the shape of a tool people could trust, even if some plumbing is still catching up.


What this repo is really teaching

The lesson is not about retail alone. It is about modeling work at the level where the work actually happens. In this case, that level is a shelf, a zone, and a path a human can follow.

Team38 OMS shows how to build an internal tool that stays coherent: spatial data model, staged operations, small backend surface area, and a frontend tuned to task flow. That combination is what makes a repository feel like an operating system for a business process instead of a dashboard with tables.