Guide · For IT teams, partners and plant admins

System Design & Architecture

How Namisite mERP is put together: the layers, the data it keeps, how stock moves when a job is produced or goods arrive, how people sign in, and how the app is deployed and scaled.

Laravel 13

PHP 8.3 MVC

MySQL 8

Single database

9 modules

One shared codebase

6 roles

Gate-based access

Contents
1

Overview

mERP is a cloud manufacturing ERP for Indian MSME plants. One Laravel application serves two faces from the same codebase and database:

Public site

merp.namisite.com

Landing page, one page per module, this guide, privacy, and the "Book a demo" form that saves a lead and emails the sales inbox.

Admin panel

merp.namisite.com/admin

Invitation-only workspace for plant staff: dashboard, production, BOMs, inventory, procurement, quality, leads, staff and settings.

Design goals

  • Runs on ordinary cPanel hosting: no Node build, no Redis, no extra servers.
  • Stock is always explained: every change writes a ledger row with a running balance.
  • No passwords: email one-time codes for every sign-in.
  • Business rules live in small services, not in screens, so they are tested once.
  • Admins change company, email and production settings in the app, not in files.
  • Mobile friendly from the start, so supervisors can work from the shop floor.
2

Architecture at a glance

A classic layered monolith. Each layer only talks to the one below it, which keeps the code easy to follow and change.

Clients

Desktop browser
Phone / tablet
Email inbox
HTTPS

Web server

Apache / LiteSpeed (cPanel) · PHP 8.3 · document root public/

Laravel 13 application

Routing & middleware

web.php, auth, active, throttle, CSRF

Controllers

Landing, Auth (OTP), 10 admin controllers

Services & gates

ProductionService, PurchaseService, 8 abilities

Eloquent models

13 models, one per table

Views · Blade + Tailwind + Alpine (CDN)
Mail · OTP and demo-alert emails, queued
Scheduler · queue worker + daily OTP clean-up
MySQL 8
business data, sessions, cache, jobs
SMTP server
set in Admin → Settings
File storage
storage/ for logs and cache files
3

Technology stack

LayerChoiceWhy
LanguagePHP 8.3Available on every Indian shared and VPS host.
FrameworkLaravel 13Routing, ORM, queues, mail, validation and tests in one package.
DatabaseMySQL 8 / MariaDB 10.6+Transactions and row locks for stock; cPanel standard.
UIBlade, Tailwind CSS 4 (CDN), Alpine.js 3Server-rendered pages, no npm build step on the server.
FontsPoppins + InterNamisite brand typography.
Sign-inEmail one-time code (6 digits)No passwords to forget, leak or reset.
Background workDatabase queue + Laravel schedulerWorks with a single cron entry; no Redis needed.
Sessions & cacheDatabase driverShared across PHP workers without extra services.
PDFBrowser print (Print / Save as PDF)Clean A4 purchase orders without a PDF library.
TestsPHPUnit 12Covers stock posting, shortages, receipts, roles and the demo form.
4

Request lifecycle

What happens when a production supervisor presses Book output on a work order:

Step 1

Browser

POST /admin/work-orders/{id}/output with CSRF token

Step 2

Middleware

Session, CSRF, auth, active-user check

Step 3

Controller

Validates input, checks the manage-production gate

Step 4

Service

ProductionService posts stock in one DB transaction

Step 5

Response

Redirect back with a status message

If anything fails inside the transaction (for example, not enough material), nothing is saved and the user sees a clear message such as "Not enough material: RM-CRCA-1.2 (short 14 kg)".

5

Modules & code map

Each module is a controller, its models and a folder of views. Shared logic sits in services.

Production

Plan → release (material check) → start → book good and rejected output → complete.

Code · WorkOrderController · ProductionService

Tables · work_orders

Bills of materials

Components with scrap %, versions, cost per unit, requirement calculator.

Code · BomController

Tables · boms, bom_lines

Inventory

Item master, reorder levels, bin locations, adjustments and the stock ledger.

Code · ItemController

Tables · items, stock_movements

Procurement

Draft → sent → partial or full goods receipt. GST %, printable PO, "PO for low stock".

Code · PurchaseOrderController · SupplierController · PurchaseService

Tables · purchase_orders, purchase_order_lines, suppliers

Quality

Incoming (against PO), in-process and final (against work order) checks: pass, fail or hold.

Code · QualityInspectionController

Tables · quality_inspections

Dashboard

Open and overdue jobs, output this month, low stock, stock value, QC pass rate, new leads.

Code · DashboardController

Tables · reads all modules

Leads

Demo form on the public site; status, notes and CSV export in admin.

Code · LandingController · DemoRequestController

Tables · demo_requests

Access

Invite staff, set role, deactivate; email-code sign-in.

Code · OtpLoginController · UserController

Tables · users, login_otps

Settings

Company details, alert inbox, SMTP (encrypted), negative-stock switch, test email.

Code · SettingsController

Tables · settings

6

Core business flows

Stock only changes through Item::moveStock(). It locks the item row, updates the balance and writes a ledger row in one transaction, so two people booking at the same moment can never get the count wrong.

Production output

ProductionService::recordOutput
  1. 1

    Check. Work order must be released or in progress.

  2. 2

    Explode BOM. Required = (good + rejected) × qty per unit × (1 + scrap %).

  3. 3

    Shortage check. Block with a clear list, unless "allow negative stock" is on.

  4. 4

    Issue. Each component: stock − required, ledger type "issue".

  5. 5

    Receive. Finished item: stock + good units, ledger type "production".

  6. 6

    Status. In progress, or completed once produced ≥ planned.

Goods receipt

PurchaseService::receive
  1. 1

    Check. PO must be sent or partly received.

  2. 2

    Validate. Each line: cannot receive more than is pending.

  3. 3

    Receive. Item stock + qty, ledger type "receipt" with PO number.

  4. 4

    Update line. received_qty goes up.

  5. 5

    Status. Partial while anything is pending, then received.

  6. 6

    Inspect. Optional incoming quality inspection against the PO.

Document lifecycles

Work order planned→ released→ in_progress→ completed or cancelled
Purchase order draft→ sent→ partial→ received or cancelled
Inspection hold→ pass or fail
Demo request new→ contacted→ demo_scheduled→ won or lost
7

Security & sign-in

Email one-time code

  1. 1Staff enters their work email at /admin/login. Only emails added on Staff & Roles get a code; others see the same neutral message.
  2. 2A 6-digit code is generated, stored as a bcrypt hash in login_otps, and emailed. It is valid for 10 minutes and works once.
  3. 3Wrong codes are counted: 5 tries per code, 5 codes per email per hour, plus request throttling per IP.
  4. 4On success the session ID is regenerated and the user lands on the dashboard.
  5. 5Every admin request re-checks that the user is still active, so a deactivated person is signed out at once.

Built-in protections

  • Served over HTTPS; session cookies are HTTP-only.
  • CSRF token on every form.
  • All input validated in controllers; Eloquent prevents SQL injection.
  • Blade escapes output by default (XSS).
  • Admin pages sent with noindex so search engines skip them.
  • SMTP password stored encrypted with the app key.
  • Rate limits on login and on the public demo form.
  • Each stock change records who made it.
8

Roles & permissions

Everyone signed in can view every screen. The role decides what they can change. Rules are Laravel gates defined in one place, AppServiceProvider::ABILITIES, and checked in controllers and views.

Can changeAdminPlant managerProductionStores & purchaseQualityViewer
Work orders: create, release, book output
Bills of materials
Items, stock adjustments
Suppliers, purchase orders, goods receipt
Quality inspections
Demo requests (leads)
Staff & roles
Company, email and production settings
9

Design decisions & roadmap

DecisionChosenTrade-off
Monolith or microservicesOne Laravel monolithSimple to host and change; split later only if a module needs its own scale.
Stock modelRunning balance on item + full ledgerFast stock lookups and a full audit trail. Multi-warehouse is a future step.
Front endServer-rendered Blade + AlpineNo build tools; less suited to offline use, which a future mobile app can cover.
TenancyOne install per customerStrong data separation; each plant gets its own database.
Sign-inEmail OTP onlyNo passwords; depends on reliable email, so SMTP is tested from Settings.

Planned next

Multi-warehouse stock Batch and serial tracking Sales orders and dispatch GST e-invoice and e-way bill REST API for Tally and other systems Machine and work-centre capacity Android app for the shop floor WhatsApp alerts
10

Glossary

BOM
Bill of materials: the components and quantities needed to make one finished item.
Scrap %
Extra material allowed for wastage when a BOM is exploded.
Work order
A shop-floor job to make a planned quantity of one item.
GRN / receipt
Goods received against a purchase order, added to stock.
Stock ledger
Every stock movement with its running balance.
Reorder level
Stock level at which an item shows as low and appears in "PO for low stock".
HSN code
Indian tax classification code for goods, used on POs.
OTP
One-time password: the 6-digit sign-in code sent by email.

Want a walkthrough with your IT team?

We'll go through the architecture, hosting and data migration for your plant.

Book a free 30-min demo