← Guides · System design

tpierp.namisite.com · v1.6

TPI ERP architecture

How the Third Party Inspection app is put together and how a vendor PO moves to a released IRN. Laravel 13 and MySQL on cPanel shared hosting, with email-code sign-in and branded emails. Staff run the workflow; customers sign in to a read-only portal that shows only their own orders.

System components

Staff and customers use the same web app from a browser or phone. All files and data stay on the cPanel account; email is the only thing that leaves it.

People Administratorfull access Resource coordinatorassigns inspectors Inspectoron site, on a phone Technical headreviews, issues IR/IRN Viewerread only Customerown orders, read only Email inbox 6-digit login code welcome + workflow alerts reads code Browser / phone Blade pages over HTTPS Tailwind + Alpine from jsDelivr CDN, no build Photo upload from camera IR / IRN A4 print Print / Save as PDF Reports CSV export Session cookie sessions table in MySQL Times shown in Asia/Kolkata (stored UTC) Customer portal /portal: orders, progress, IR / IRN print cPanel shared hosting · document root tpierp/public Apache + .htaccess HTTPS for tpierp.namisite.com → public/index.php Laravel 13 app Middleware guest · auth · active (deactivated user or client = signed out) · role checks per screen Email-code sign-in OtpLoginController 6 digits, 10 min expiry single use, 5 tries 5 sends per hour same reply for unknown emails login_otps table Screens (controllers) VendorPo · PoItem Assignment · Inspection Review · Report Dashboard · Master User · Setting · Log CustomerPortal File (private download) Rules and services Numbering TPI / CN / IR / IRN, per FY StageStatus status moves, qty checks FileStore private uploads, 20 MB Notify queues emails, never blocks MySQL masters, POs, items, stages, assignments, reports, photos, settings, sequences, activity, sessions, jobs Private file storage storage/app/private/tpi PO files, stage files, photos served only via /files/… to signed-in users allowed to see Mail queue jobs table (database queue) login codes, welcome + workflow mails branded HTML templates SMTP mail server host, port, user, from address set under Settings (no .env edit) cPanel cron, every minute schedule:run → queue:work model:prune daily (old login codes) emails go out
Blue arrows are web requests; gold arrows are email. Mail is queued in MySQL and sent by the per-minute cron, so a slow mail server never holds up a screen.

Inspection workflow

Each row is a role. A PO is split into items, each item into the inspection stages ticked for it, and every stage moves through its own status.

Administratormasters, POs Coordinatorplans visits Inspectorown visits only Technical headdecides 1 · Vendor PO vendor, client, PO files TPI/26-27/0001 2 · Items + stages qty checked vs PO, tick inspection stages CN-0001 3 · Assign inspector location, dates, notes, control files emails inspector 4 · Inspection report offered / accepted / rejected qty + photos emails technical heads 5 · Review approve, hold or reject emails inspector + coord. IR/26-27/0001 6 · Release IRN Inspection Release Note A4 print / PDF IRN/26-27/0001 Hold: back to the same inspector Rejected or balance qty left: coordinator sends a new visit Stage status Pending Assigned Awaiting review Approved On hold Rejected IRN released Numbers come from Settings → Number formats. {FY} is the Indian financial year (26-27) and counters restart each year. A stage stays "Approved" after an IRN while balance qty remains.
Solid arrows are the normal path. Dashed arrows send work back: orange to the same inspector, red to the coordinator for a new visit. Every action is written to the activity log. Customers see each stage move in their portal as it happens.

Who can do what

RoleMasters, POs, itemsAssign visitsSubmit reportsApprove, IR, IRNReportsStaff, settings, log
AdministratorYesYesYesYesYesYes
Resource coordinatorView POs, upload control filesYes––Yes–
Inspector––Own visits only–––
Technical headView––YesYes–
ViewerView–––View–
CustomerOwn client's POs and items only (progress)–––Own approved IR / IRN–

Welcome email

When an admin adds a staff member or customer login with Send a welcome email ticked (the default), the person gets a branded email telling them where to go, which email to sign in with, what role they have and what that role can do. There is no password: the email explains the emailed-code sign-in.

Admin saves a user Staff & Roles → + Add staff Clients → + Login or Edit: turn an inactive user on or Send / Resend welcome on the row UserController only if active and box ticked queues WelcomeMail stamps users.welcomed_at logs user.welcomed cron Welcome email Portal link (APP_URL) Sign-in email, role, designation Company (customer logins), added by 3 steps: open, enter email, enter code What you can do as <role> text per role: config/tpi.php role_guides light + dark mode, Outlook button Open TPI ERP button /login?email=… email already filled in then the usual 6-digit code
Gold is email. Like every other email it goes through the mail queue, so saving the user never waits on the mail server. Covered by tests in tests/Feature/WelcomeEmailTest.php.

Workflow emails

Each step of an inspection sends its own branded email, in the same style as the welcome email: logo and gold rule, a coloured status label, a five-step tracker (Assigned → Report submitted → Technical review → Approved (IR) → IRN released) showing where the job is, the key numbers as tiles, a details table and one button that opens the right page. They work in light and dark mode, on phones, and in Outlook.

WhenTo (copy)What it showsButton
Visit assignedInspector (coordinator)Scheduled dates, location, qty, coordinator's instructions, PO / item / stage, what the report must includeOpen inspection
Visit details changedInspector (coordinator)Same email marked "Inspection updated". A new inspector gets the normal assigned emailOpen inspection
Report submittedAll active Technical Heads (coordinator)Offered / accepted / rejected qty, inspector's remarks, photo count, stage qty, how many reports are waiting. Marked "Resubmitted after hold" the second timeReview report
ApprovedInspector (coordinator)IR number, accepted qty, stage balance, reviewer's remarksView report
On holdInspector (coordinator)The reason, who gave it and when, what to do nextUpdate and resubmit
RejectedInspector (coordinator)The reason, plus a next-step note for the coordinator to assign a re-inspection for the balanceView report
IRN releasedInspector (coordinator)IRN and IR numbers, released qty, "Item complete" when every stage is doneView / print IRN
IRN releasedThe client's customer loginsTheir PO, item, stage, IR / IRN numbers. No internal remarksView / print IRN in the portal

Code

  • app/Mail/InspectionAssignedMail, ReportSubmittedMail, ReviewDecisionMail, IrnReleasedMail (base InspectionMail)
  • Views in resources/views/emails/inspection/, shared layout emails/layouts/tpi and parts in emails/partials/
  • Sent from the Assignment, Inspection and Review controllers through Notify::send (queued; a mail error never blocks the action)

Settings

  • Send workflow emails turns all of them on or off
  • Also email the client's customer logins when an IRN is released (on by default)
  • Workflow email previews: open any email with sample data; nothing is sent

Tests

  • tests/Feature/WorkflowEmailTest.php walks assign → submit → hold → resubmit → reject, and approve → IRN, checking recipients, subjects and the reason text
  • Run against MySQL strict mode as well as SQLite

Customer portal

A customer login is a user with the role client and a client_id. It opens only the portal screens, and every query there is filtered to that client's vendor POs. It cannot change anything.

Who Customer login role client users.client_id → client same email-code sign-in added by admin: Clients → + Login inactive client = signed out Check and filter CustomerPortalController gate view-portal on every action every query: vendor_pos.client_id = user.client_id another client's order → 404, so its existence is never revealed What the customer sees (/portal) My Orders open / closed POs, items completed, progress bar, search Order detail each item's stages, approved qty, inspection dates, IR / IRN links Completed & Reports approved IR and IRN (print / PDF) with photos, completed items Plain status words in the portal Not started Inspection scheduled Under review On hold Re-inspection due Approved Released (IRN) Progress = stages done ÷ all stages. A stage is done when its IRN is released, or it is approved for the full quantity. An item is completed when every stage is released. Blocked for customers All staff screens (403) · other clients' orders (404) · PO files and stage control files · pending, held or rejected reports · reviewer remarks · inspector photos of unapproved visits
Gold is the customer path. The portal reuses the same IR / IRN print page as staff, but only for reports that already have an IR number. Covered by tests in tests/Feature/CustomerPortalTest.php.

Routes

  • GET /portal · My Orders
  • GET /portal/orders/{po} · order detail
  • GET /portal/completed · completed items and reports
  • GET /portal/reports/{report}/print · IR, or IRN with ?doc=irn
  • /dashboard sends customers to /portal

Files

  • /files/photo/{id} is allowed only for photos of an approved report on the customer's own PO
  • PO documents and stage control files stay staff-only

Setting up a customer

  • Give each vendor PO the right Client
  • Clients → + Login, or Staff & Roles → + Customer login
  • Several logins per client are fine; Logins on the client row lists them

Data model

The main tables follow the workflow one-to-many, left to right.

vendor_pos→po_items→item_stages→assignments→inspection_reports→inspection_photos

Attached files

po_documentsstage_documents

Rows point to files in private storage.

Masters

clientsvendorsunitsstages

Default stages and units come from the seeder.

Customer link

users.client_idclientsvendor_pos.client_id

A customer login and a vendor PO point at the same client. That shared client_id is the only thing the portal filters on.

System

userslogin_otpssettingssequencesactivity_logssessionsjobs

sequences holds the per-year counters for PO, CN, IR and IRN numbers.