Initializing
Back to Projects
Year2024
DomainFullstack
AccessOpen Source
Complexity0 / 10
Next.jsTypeScripttRPCPrismaMySQLRedisMulti-TenancyRazorpayInvoice SystemSaaS
FullstackArchived

Water Industry System (WIS) - Enterprise ERP

A comprehensive enterprise resource management system for water jar distribution businesses with multi-tenancy, invoicing, jar tracking, and Razorpay payment integration.

Parsing system architecture diagram...

Technology Stack

LayerTechnologyVersion/Details
FrontendNext.js16.0.4 (App Router)
LanguageReact19.2.0
LanguageTypeScript^5.x
StylingTailwind CSS^4
UI Componentsshadcn/uiRadix UI primitives
Backend FrameworktRPC11.7.2
AuthenticationNext-Auth^5.0.0-beta.30
Database ORMPrisma5.22.0
DatabaseMySQL8.0+
CachingRedisLatest
LoggingWinston^3.18.3
ChartsChart.js + Recharts-
AnimationsFramer Motion^12.23.24
PDF Generation@react-pdf/renderer^4.3.1
PaymentsRazorpay^2.9.6
EmailNodemailer^7.0.11
ValidationZod^4.1.13
StateZustand^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

  1. Multi-Tenant SaaS Architecture: The system supports multiple organizations on a single instance, with complete data isolation and subscription-based access control.
  1. Real-Time Jar Tracking: Atomic jar movement logging provides complete audit trails for every jar, from plant to delivery and back.
  1. Financial Integration: Comprehensive invoicing system with PDF generation, payment tracking, and credit ledger management.
  1. Role-Based Access Control: Three-tier security model (Admin, Employee, Developer) with fine-grained permissions and audit logging.
  1. 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:

typescript
// 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:

typescript
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:

code
PENDINGIN_PROGRESSCOMPLETEDAPPROVED

Features:

  • 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:

typescript
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:

typescript
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:

typescript
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:

typescript
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:

typescript
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:

typescript
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

typescript
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

typescript
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

typescript
// 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

typescript
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

typescript
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)

RouterDescription
industryIndustry CRUD, price zone assignment
tripTrip creation, assignment, status management
transactionSales recording, payment processing
invoiceInvoice creation, payment tracking
jarInventory management, movement tracking
expenseExpense recording, category management
employeeEmployee profile management
reportAnalytics, revenue trends, expense breakdowns
razorpaySubscription billing, payment collection
settingsSystem configuration, organization settings
auditAudit 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

bash
# 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 start

Default Credentials

RoleEmailPassword
Admin[email protected]admin123
Employee[email protected]employee123

Docker Production Deployment

bash
# Full stack deployment
docker-compose up -d --build

Services:

  • 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.

Submit a Technical Suggestion