A multi-tenant inventory management and order-processing system built with Ruby on Rails. Multiple companies (tenants) can each manage their own products, warehouses, suppliers, and stock. Every stock change is recorded as an immutable ledger entry rather than a mutable "quantity" field, so stock levels are always derived and auditable.
- Multi-tenant: each
Companyis fully isolated; users belong to exactly one company and only ever see that company's data. Covered by an automated test suite (see Testing below). - Self-serve sign-up: anyone can create a new company and its first admin user from the sign-up page, no console access needed.
- Team management: admins can see the full member roster (email, role, join date) and the complete invitation history (pending, accepted, or expired), not just an in-flight queue. Invites are link-based (no email delivery): each generates a unique, expiring link (7 days) the admin shares manually, and pending ones can be revoked.
- Role-based access:
viewer(read-only),staff(day-to-day operations: create/edit records, receive purchase orders, fulfill sales orders, transfer stock, record manual adjustments, import products), andadmin(everything staff can do, plus deleting records and managing the team). Enforced in controllers, views, and covered by an automated test suite. - Product catalog: SKUs, categories, unit pricing, and per-product reorder thresholds, with low-stock highlighting throughout the UI.
- CSV import/export for products: export the full catalog (including a computed total-stock-on-hand column for reference) or bulk create/update products by uploading a CSV matched on SKU. Stock itself is never touched by import, since every stock change has to go through the ledger.
- Warehouses & suppliers: track stock across multiple physical locations and the suppliers you buy from.
- Multi-warehouse transfers: move stock between warehouses for the same company, with validation that there's enough stock at the source.
- Manual stock adjustments: add initial stock, correct counts after a physical audit, or record damage/shrinkage directly, without needing a purchase order. Requires a reason, which shows up in the ledger.
- Stock ledger: every stock change (purchase receipt, sale, manual
adjustment, transfer) is recorded as a
StockMovement. Current stock on hand is computed by summing the ledger, never stored redundantly. The ledger is browsable and filterable by product or warehouse. - Purchase orders: draft, order, receive workflow with dynamically addable/removable line items (no page reload, powered by Stimulus). Receiving stock generates the corresponding ledger entries automatically.
- Sales orders: draft, confirm, fulfill workflow, same dynamic line item editing. Fulfilling an order deducts stock via the same ledger mechanism.
- Dashboard: at-a-glance counts, a low-stock list, and a feed of recent stock movements.
- Ruby 3.3+ / Rails 8
- SQLite (Rails 8 defaults, used for the primary DB as well as Solid Queue/Cache/Cable)
- Active Storage with libvips for image variants
- Turbo & Stimulus (Hotwire) for interactivity, no separate JS build step (import maps)
- Session-based authentication via Rails 8's built-in
has_secure_passwordauthentication generator, extended with token-based team invites (has_secure_token) - Hand-rolled role-hierarchy authorization (no external gem: the permission model is a simple viewer/staff/admin rank check, not per-resource ownership rules, so a full policy-object gem like Pundit would be more machinery than the problem needs)
- Minitest (Rails' default) for integration tests covering tenant isolation and role enforcement
- Plain CSS design system (no framework): light neutral surfaces with a steel-blue accent, monospace reserved for tabular data (SKUs, quantities, currency)
You'll need Ruby 3.3+, Rails 8, SQLite, and libvips installed. The
recommended way to install Ruby is via a version manager (rbenv) rather
than your OS's system package:
Install rbenv + ruby-build, then a Ruby version:
# Arch / Garuda
sudo pacman -S rbenv
# Debian / Ubuntu
sudo apt install rbenv
# macOS
brew install rbenv
rbenv init # follow the shell hook instructions it prints, then restart your shell
rbenv install 3.3.6
rbenv global 3.3.6
ruby -v # confirm 3.3.xInstall Rails 8:
gem install rails -v '~> 8.0'
rbenv rehash
rails -v # confirm 8.x.xInstall SQLite dev libraries (needed to build the sqlite3 gem's
native extension):
# Arch / Garuda
sudo pacman -S sqlite
# Debian / Ubuntu
sudo apt install libsqlite3-dev
# macOS
brew install sqlite3Install libvips (needed for Active Storage image variants):
# Arch / Garuda
sudo pacman -S libvips
# Debian / Ubuntu
sudo apt install libvips
# macOS
brew install vipsNote on Ruby 3.4+: csv was unbundled from Ruby's default standard
library starting in 3.4, so it needs to be an explicit Gemfile
dependency (already included: gem "csv").
git clone <this-repo-url>
cd inventory_erp
bundle install
bin/rails db:setup # creates the DB, loads the schema, runs db/seeds.rb if present
bin/rails serverVisit http://localhost:3000 and click "Create a company account" to sign
up, or sign in if you already have an account. To seed initial stock for a
new product, use "New adjustment" from the Stock ledger page rather than
the console.
bin/rails testTwo integration test files cover the guarantees the multi-tenant design depends on:
test/integration/tenant_isolation_test.rb: a user from one company can't view, edit, delete, or see in a listing another company's data, even when using the highest-privileged (admin) role, which confirms the block comes from tenant scoping itself and not incidentally from a role check.test/integration/role_enforcement_test.rb: viewers can't create or delete anything and are redirected away from forms they try to reach directly by URL; staff can create but not delete; only admins can delete or reach the team management page.
Core data model, business logic, controllers/views for all core resources, the dashboard, self-serve sign-up, team management, dynamic order line items, role-based access control, multi-warehouse transfers, manual stock adjustments, CSV import/export, and an automated test suite for tenant isolation and role enforcement are all in place and usable end-to-end.