Technology Stack
| Layer | Technology | Version/Details |
|---|---|---|
| Frontend | Next.js | 16.0.4 (App Router) |
| Language | React | 19.2.0 |
| Language | TypeScript | ^5.x |
| Styling | Tailwind CSS | ^4 |
| UI Components | shadcn/ui | Radix UI primitives |
| Backend Framework | tRPC | 11.7.2 |
| Authentication | Next-Auth | ^5.0.0-beta.30 |
| Database ORM | Prisma | 5.22.0 |
| Database | MySQL | 8.0+ |
| Caching | Redis | Latest |
| Logging | Winston | ^3.18.3 |
| Charts | Chart.js + Recharts | - |
| Animations | Framer Motion | ^12.23.24 |
| PDF Generation | @react-pdf/renderer | ^4.3.1 |
| Payments | Razorpay | ^2.9.6 |
| Nodemailer | ^7.0.11 | |
| Validation | Zod | ^4.1.13 |
| State | Zustand | ^5.0.8 |
Purpose and Philosophy
Water Industry System (WIS) is a comprehensive enterprise resource planning platform designed specifically for water jar distribution businesses. The system manages the complete lifecycle of water jar delivery operations, from customer management to trip planning, transaction recording, and financial reporting.
The core philosophy centers on "Operational Visibility" - providing complete transparency into every aspect of the water distribution business. Every jar movement, every transaction, and every delivery is tracked and logged, enabling data-driven decision making and operational efficiency.
Core Design Principles
- Multi-Tenant SaaS Architecture: The system supports multiple organizations on a single instance, with complete data isolation and subscription-based access control.
- Real-Time Jar Tracking: Atomic jar movement logging provides complete audit trails for every jar, from plant to delivery and back.
- Financial Integration: Comprehensive invoicing system with PDF generation, payment tracking, and credit ledger management.
- Role-Based Access Control: Three-tier security model (Admin, Employee, Developer) with fine-grained permissions and audit logging.
- Production-Ready: Docker containerization, Nginx reverse proxy, Redis caching, automated backups, and health checks.
Core Modules
1. Industry Management
Customer (industry) management with credit tracking:
// Industry model
model Industry {
id String @id @default(uuid())
industryName String @map("industry_name")
customerName String @map("customer_name")
contactNumber String? @map("contact_number")
status IndustryStatus @default(ACTIVE)
creditBalance Decimal @default(0.00) @map("credit_balance")
billingContactName String? @map("billing_contact_name")
billingEmail String? @map("billing_email")
billingAddress String? @map("billing_address")
taxId String? @map("tax_id")
paymentTerms String? @map("payment_terms")
}Features:
- Create, update, delete industries
- Grid and List view options
- Real-time search filtering
- Credit balance tracking
- Billing details management
2. Trip Management
Delivery trip orchestration with inventory tracking:
model Trip {
id String @id @default(uuid())
tripNumber String @unique
totalJars Int
remainingJars Int
totalCollected Decimal
totalCredited Decimal
jarsLoaded Int
jarsDelivered Int
jarsReturnedFilled Int
jarsReturnedEmpty Int
jarsDifference Int
openingTotalCredit Decimal
creditChangeOnTrip Decimal
closingTotalCredit Decimal
status TripStatus @default(PENDING)
createdBy String
startedAt DateTime?
completedAt DateTime?
approvedAt DateTime?
}Trip Workflow:
PENDING → IN_PROGRESS → COMPLETED → APPROVEDFeatures:
- Create and assign trips to employees
- Real-time trip monitoring (5-second auto-refresh)
- Jar inventory tracking (Full/Empty, Sold/Returned)
- Financial breakdown (Total, Paid, Credit amounts)
- Trip reconciliation with credit ledger
3. Transaction Management
Sales recording with split payments:
model Transaction {
id String
tripId String
employeeId String
industryId String
jarCount Int
pricePerJar Decimal
totalAmount Decimal
amountPaid Decimal
amountCredited Decimal
previousCreditBalance Decimal
newCreditBalance Decimal
transactionDate DateTime
notes String?
}Features:
- Split payments (Cash and Credit)
- Automatic credit balance calculation
- Jar count validation (prevent overselling)
- Past due and total due tracking
4. Jar Management System
Complete jar lifecycle tracking:
model JarInventory {
id String @id @default(uuid())
totalOwnedJars Int @default(0)
filledAtPlant Int @default(0)
emptyAtPlant Int @default(0)
jarsInTransit Int @default(0)
jarsInMarket Int @default(0)
}
model JarMovement {
id String @id @default(uuid())
industryId String?
tripId String?
movementType MovementType
jarCount Int
fromLocation LocationType
toLocation LocationType
notes String?
createdBy String
createdAt DateTime @default(now())
}
enum MovementType {
DELIVERED
COLLECTED
PLANT_ADJUST
WALKIN_RETURN
LOST
PURCHASED
TRIP_LOAD
TRIP_RETURN
}Features:
- Global inventory dashboard
- Per-industry jar tracking (empty/filled)
- Atomic movement logging with audit trail
- Admin jar collection interface
- Employee one-click collection
- Stock adjustment tools
- Walk-in return processing
5. Comprehensive Invoice System
Professional billing with PDF generation:
model Invoice {
id String
invoiceNumber String @unique
industryId String
tripId String?
invoiceDate DateTime
dueDate DateTime
subtotal Decimal
discountAmount Decimal
discountReason String?
taxAmount Decimal
taxRate Decimal
totalAmount Decimal
previousCreditBalance Decimal
advancePayment Decimal
amountDue Decimal
status InvoiceStatus
paymentStatus PaymentStatus
accessToken String @unique
tokenExpiresAt DateTime?
}
enum InvoiceStatus {
DRAFT
ACTIVE
PAID_PENDING_VERIFICATION
VERIFIED
CANCELLED
}
enum PaymentMode {
CASH
UPI
BANK_TRANSFER
CHEQUE
CREDIT
}Features:
- Admin invoice management with dynamic line items
- Customer portal with secure token-based access
- Payment submission workflow
- Multiple payment modes
- PDF generation with company branding
- Automatic credit ledger integration
6. Financial Management
Expense tracking and profit analysis:
model Expense {
id String @id @default(uuid())
amount Decimal
date DateTime
description String?
categoryId String
recordedBy String
}
model ExpenseCategory {
id String @id @default(uuid())
name String
description String?
isDefault Boolean @default(false)
}Features:
- Record daily operating costs
- Custom expense categories
- Manufacturing cost per jar configuration
- Revenue vs Expenses vs Profit analysis
7. Event Reminders
Bulk order planning and alerts:
model EventReminder {
id String @id @default(uuid())
eventDate DateTime
industryId String
requiredJars Int
advancePayment Decimal?
remark String?
status ReminderStatus @default(ACTIVE)
reminderStart DateTime // Auto-calc: eventDate - 3 days
}Features:
- 3-day advance warning dashboard widget
- Future jar requirements planning
- Employee reminder management
- Status tracking (Active, Completed, Cancelled)
8. Pricing Zones
Flexible pricing management:
model PriceZone {
id String @id @default(uuid())
zoneName String
pricePerJar Decimal
isActive Boolean @default(true)
}
model IndustryPriceZone {
id String @id @default(uuid())
industryId String
zoneId String
assignedAt DateTime @default(now())
}Multi-Tenancy & SaaS Features
Organization Management
model Organization {
id String @id @default(uuid())
name String
slug String @unique
domain String? @unique
planId String?
plan PricingPlan?
status OrganizationStatus @default(ACTIVE)
trialEndsAt DateTime?
maxUsers Int @default(10)
maxIndustries Int @default(100)
users User[]
industries Industry[]
}
model OrganizationServiceLimit {
organizationId String
maxActiveUsers Int
maxIndustries Int
maxEmployees Int
maxTripsPerMonth Int
enabledServices Json
storageQuotaGB Int
apiCallsPerDay Int
}Razorpay Integration
model PricingPlan {
name String
priceInr Int
billingCycle String
maxUsers Int
maxIndustries Int
maxInvoices Int
apiAccess Boolean
whiteLabelBranding Boolean
}
model RazorpayTransaction {
razorpayOrderId String @unique
razorpayPaymentId String? @unique
razorpaySignature String?
amountInr Int
status String
collectedByUserId String
}Security & Access Control
Authentication with Next-Auth v5
// Auth configuration
import NextAuth from "next-auth"
import { PrismaAdapter } from "@auth/prisma-adapter"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: "jwt" },
pages: { signIn: "/login" },
callbacks: {
async jwt({ token, user }) {
if (user) {
token.role = user.role
token.organizationId = user.organizationId
}
return token
},
async session({ session, token }) {
session.user.role = token.role
session.user.organizationId = token.organizationId
return session
}
}
})Role-Based Access Control
enum Role {
ADMIN
EMPLOYEE
DEVELOPER
}
// Protected procedure
const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
if (!ctx.user) {
throw new TRPCError({ code: 'UNAUTHORIZED' })
}
return next({ ctx: { user: ctx.user } })
})
const adminProcedure = protectedProcedure.use(async ({ ctx, next }) => {
if (ctx.user.role !== 'ADMIN' && ctx.user.role !== 'DEVELOPER') {
throw new TRPCError({ code: 'FORBIDDEN' })
}
return next()
})Audit Logging
model AuditLog {
id String @id @default(uuid())
userId String
action String
entityType String
entityId String
oldValues Json?
newValues Json?
ipAddress String?
userAgent String?
createdAt DateTime @default(now())
}API Endpoints (tRPC Routers)
| Router | Description |
|---|---|
industry | Industry CRUD, price zone assignment |
trip | Trip creation, assignment, status management |
transaction | Sales recording, payment processing |
invoice | Invoice creation, payment tracking |
jar | Inventory management, movement tracking |
expense | Expense recording, category management |
employee | Employee profile management |
report | Analytics, revenue trends, expense breakdowns |
razorpay | Subscription billing, payment collection |
settings | System configuration, organization settings |
audit | Audit log retrieval |
Dashboard Features
Admin Dashboard
- Revenue Trend (Line Chart) - 7-day analysis
- Industry Distribution (Doughnut Chart) - Top 5 by sales
- Monthly Performance (Bar Chart) - 6-month history
- Expense Distribution (Polar Area Chart)
- KPI cards with animated counters
Reports Page
- Daily sales summary
- Product-wise sales
- Expense breakdown
- Profit margin analysis
- Date range filtering
- CSV export
Build and Run
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env
# Configure DATABASE_URL, AUTH_SECRET, RAZORPAY keys, REDIS_URL
# Start infrastructure
docker-compose up -d
# Run database migrations
npx prisma migrate dev
# Seed database (optional)
npx tsx prisma/seed.ts
# Development
npm run dev
# Production build
npm run build
npm startDefault Credentials
| Role | Password | |
|---|---|---|
| Admin | [email protected] | admin123 |
| Employee | [email protected] | employee123 |
Docker Production Deployment
# Full stack deployment
docker-compose up -d --buildServices:
- Next.js application
- MySQL database
- Redis cache
- Nginx reverse proxy
Conclusion
Water Industry System (WIS) represents a sophisticated enterprise solution for water distribution businesses. The project demonstrates:
- Full-stack TypeScript development with Next.js 16
- Type-safe API with tRPC v11
- Multi-tenant SaaS architecture
- Real-time inventory tracking with atomic movements
- Professional invoicing with PDF generation
- Payment integration with Razorpay
- Comprehensive audit logging
- Docker containerization for production
The system handles the complete operational lifecycle from customer management to delivery tracking, financial reporting, and subscription billing, making it a complete ERP solution for the water jar distribution industry.
(End of file - 591 lines)
Architecture Feedback
Spotted a potential optimization or antipattern? Let me know.