# System Admin Portal - Business Logic & Rules

**Document Type:** Business Rules Specification

**Module:** System Admin Web Portal

**Platform:** Laravel Web Application

**Version:** 1.0

**Last Updated:** February 6, 2026

**Prepared By:** Business Analyst + Technical Lead

---

## Document Purpose

This document defines all business logic, rules, calculations, validations, and decision-making criteria for the System Admin Web Portal of the Lion POSM Module. It serves as the authoritative reference for developers implementing admin features and QA teams validating system behavior.

**Related Documents:**

- System Architecture & Feature Breakdown
- Database Schema & ERD
- System Admin Web Portal - Wireframes
- Mobile App API Specification

---

## Table of Contents

1. [System-Wide Business Rules](#system-wide)
2. [Product Management Logic](#products)
3. [Inventory Management Logic](#inventory)
4. [Location Management Logic](#locations)
5. [Outlet & Norms Management Logic](#outlets)
6. [Event Stock Management Logic](#events)
7. [User & Hierarchy Management Logic](#users)
8. [Depletion Planning Logic](#depletion)
9. [Order Management Logic](#orders)
10. [Reporting Logic](#reports)
11. [Notification Logic](#notifications)
12. [Audit & Security Logic](#audit)

---

<a name="system-wide"></a>

## 1. System-Wide Business Rules

### 1.1 General System Rules

**Currency & Localization:**

- **Currency:** LKR (Sri Lankan Rupee) only
- **No multi-currency support**
- **Timezone:** Asia/Colombo (GMT+5:30) - all timestamps stored in UTC, displayed in Asia/Colombo
- **Language:** English only
- **Date Format:** DD/MM/YYYY (configurable in settings, default)
- **Time Format:** 24-hour format

**Numeric Precision:**

- **Currency values:** 2 decimal places (e.g., 1,250.50)
- **Quantities:** 2 decimal places (e.g., 15.50 units)
- **Percentages:** 1 decimal place (e.g., 10.5%)
- **GPS coordinates:** 8 decimal places for latitude, longitude
- **Distance:** 2 decimal places in meters or kilometers

**Session Management:**

- **Session timeout:** 30 minutes of inactivity (configurable)
- **Concurrent sessions:** Allowed on multiple devices
- **Force logout:** On password change
- **Remember me:** 30 days cookie expiry

**Data Retention:**

- **Soft deletes:** Users, outlets, products, warehouses, distribution points, event suppliers
- **Hard deletes (cascade):** Child records (order items, shipment items, etc.)
- **Audit logs:** Minimum 2 years retention
- **Notifications:** 6 months retention
- **Inventory movements:** Permanent (financial compliance)

---

### 1.2 Access Control Rules

**Role Hierarchy:**

```
System Admin (full access)
  ↓
Senior Manager (SM)
  ↓
Territory Manager (TM)
  ↓
LSR (Sales Representative)
```

**System Admin Permissions:**

- **Full CRUD** on all entities
- **User management:** Create, edit, deactivate users
- **Master data:** Products, warehouses, distribution points, outlets
- **Norms configuration:** Create and assign norms templates
- **Event management:** Create delivery notes, manage budgets
- **Hierarchy management:** Configure organizational structure
- **System settings:** Configure system-wide parameters
- **Reports:** Generate and export all reports
- **Audit logs:** View all system activity

**Data Scope Rules:**

- **System Admin:** Can view and manage ALL data across all hierarchies
- **SM/TM/LSR:** Data scoped to their assigned hierarchy (enforced at application layer, not database)
- **Distribution Point Contacts:** Only see data for their distribution point
- **Event Suppliers:** Only see their own delivery notes

**Cascade Delete Protection:**

- **Cannot delete** a warehouse if it has inventory
- **Cannot delete** a distribution point if it has inventory or assigned outlets
- **Cannot delete** a product if it appears in any order, shipment, or delivery note
- **Cannot delete** an outlet if it has open orders or recent availability reports (within 30 days)
- **Cannot delete** a user if they have created orders or reports
- **Soft delete** instead, which hides the entity from active queries

---

### 1.3 Validation Rules (Global)

**String Length Limits:**

- **Names** (users, products, outlets): Max 255 characters
- **Codes** (SKU, RT code, warehouse code): Max 100 characters
- **Emails:** Max 255 characters, valid email format
- **Phone numbers:** Max 20 characters, allow +, spaces, hyphens
- **Addresses:** Max 500 characters (TEXT field)
- **Notes/Comments:** Max 1000 characters
- **Descriptions:** Max 2000 characters

**Code Format Rules:**

- **Product SKU:** Alphanumeric + dash/underscore, no spaces (e.g., `LL330`, `BANNER-6X3`)
- **Warehouse Code:** Alphanumeric + dash, uppercase (e.g., `MW001`)
- **Distribution Point Code:** Alphanumeric + dash, uppercase (e.g., `CDC001`)
- **Outlet RT Code:** Alphanumeric + dash, uppercase (e.g., `RT001`)
- **Budget Code:** Alphanumeric + dash, uppercase (e.g., `BUDGET-2026-Q1`)
- **All codes:** Must be unique within their entity type

**Email & Phone Validation:**

- **Email:** Must be valid format, lowercase normalization
- **Phone:** Sri Lankan format preferred (`+94XXXXXXXXX`), but flexible for international
- **Duplicate check:** Email must be unique per user

**Geo-location Validation:**

- **Latitude:** -90 to +90 (decimal degrees)
- **Longitude:** -180 to +180 (decimal degrees)
- **Tolerance:** 50 meters (system-wide, not configurable per outlet)
- **Validation:** Warn but don't block if mismatch, log discrepancy

---

### 1.4 Auto-Generation Rules

**Auto-Generated Identifiers:**

| Entity | Format | Example | Logic |
| --- | --- | --- | --- |
| Depletion Plan | `DEPL-{ID}` | `DEPL-3001` | Sequential ID |
| Shipment | `SHIP-{ID}` | `SHIP-5001` | Sequential ID |
| Order | `ORD-{ID}` | `ORD-2001` | Sequential ID |
| Delivery Note | `DN-{ID}` | `DN-8001` | Sequential ID |
| Return Note | `RN-{ID}` | `RN-9001` | Sequential ID |
| QR Code (Shipment) | `SHIP-{ID}` | `SHIP-5001` | Plain text, same as shipment number |
| QR Code (Delivery Note) | `DN-{ID}` | `DN-8001` | Plain text, same as delivery note number |

**Auto-Generation Timing:**

- **Generated on creation** (INSERT)
- **Immutable** after creation (cannot be changed)
- **Sequential** (no gaps, but may not be strictly consecutive due to transaction rollbacks)
- **No prefix customization** by user

**QR Code Generation:**

- **Format:** Plain text (no encryption)
- **Content:** Entity identifier (e.g., `SHIP-5001`)
- **Encoding:** UTF-8
- **QR Code Type:** QR Code Version 2 (25x25 modules) or higher
- **Error Correction:** Level M (15% recovery)
- **Reusable:** Same QR for delivery and return (for event stock)

---

<a name="products"></a>

## 2. Product Management Logic

### 2.1 Product Creation Rules

**Required Fields:**

- SKU (must be unique)
- Product Name
- Category (from predefined list)
- Unit Price (LKR, must be ≥ 0)

**Optional Fields:**

- Description
- Product Image (max 2MB, JPG/PNG only)
- Initial Stock (defaults to 0 if not provided)
- Reorder Level (defaults to 0 if not provided)
- Unit of Measure (defaults to "Each")

**Default Values:**

- **Status:** Active
- **Unit Price:** 0.00
- **Initial Stock:** 0
- **Reorder Level:** 0
- **Unit of Measure:** "Each"

**Validation Rules:**

- **SKU uniqueness:** Case-insensitive check
- **Unit Price:** Must be ≥ 0, max 12 digits, 2 decimals (e.g., 9999999999.99)
- **Initial Stock:** Must be ≥ 0
- **Reorder Level:** Must be ≥ 0
- **Image upload:** Validate MIME type (image/jpeg, image/png), max 2MB

---

### 2.2 Product Update Rules

**Editable Fields:**

- Product Name
- Description
- Category
- Unit Price
- Reorder Level
- Unit of Measure
- Product Image
- Status (Active/Inactive)

**Non-Editable Fields:**

- **SKU:** Cannot be changed after creation (to prevent broken references)
- **ID:** System-generated, immutable
- **Created At:** System-generated, immutable

**Price Change Logic:**

- **Historical orders/shipments:** Retain original price at time of creation
- **Future orders/shipments:** Use new price
- **Inventory valuation:** Update weighted average cost on next stock inward
- **No price history tracking:** Only current price stored

**Status Change Impact:**

- **Active → Inactive:** Product hidden from dropdowns, cannot be added to new orders
- **Inactive → Active:** Product becomes available again
- **Inactive products:** Still visible in historical data (orders, shipments, reports)

---

### 2.3 Product Deletion Rules

**Soft Delete Conditions:**

- **Can soft delete IF:**
    - No open orders contain this product
    - No pending shipments contain this product
    - No active delivery notes contain this product
    - No inventory movements in last 30 days

**Cannot Delete IF:**

- Product is referenced in ANY order (any status)
- Product is referenced in ANY shipment (any status)
- Product is referenced in ANY delivery note (any status)
- Product has current inventory > 0 at any location

**Soft Delete Behavior:**

- **Marked as deleted:** `deleted_at` timestamp set
- **Hidden from UI:** Not shown in active product lists
- **Audit trail:** Deletion logged in audit_logs table
- **Retained in reports:** Still visible in historical reports

**Hard Delete:**

- **Not supported** via UI
- **Database cleanup:** Manual DBA operation only, after 2+ years

---

### 2.4 Product Categories

**Category Types:**

- **Beer:** Lager, Stout, Strong, etc.
- **Equipment:** Coolers, ice buckets, etc.
- **POSM:** Banners, table tents, signage, etc.
- **Custom:** Admin-defined categories

**Category Management:**

- **CRUD operations:** Admin can create, edit, deactivate categories
- **Cannot delete** category if products are assigned
- **Hierarchy:** Flat list (no sub-categories)
- **Sorting:** Alphabetical by default

---

<a name="inventory"></a>

## 3. Inventory Management Logic

### 3.1 Inventory Location Rules

**Location Types:**

- **Warehouse:** Central storage
- **Distribution Point:** Regional distribution centers

**Inventory Ledger:**

- **One record per:** (Product, Location Type, Location ID)
- **Tracks:** Available quantity, reserved quantity
- **Reserved quantity:** Stock allocated to approved depletion plans (status: Ready to Deplete)

**Available Stock Calculation:**

```
Available for Orders = Total Quantity - Reserved Quantity
```

**Example:**

- **Total Quantity:** 500 units
- **Reserved Quantity:** 150 units (for approved depletion plans)
- **Available for Orders:** 350 units

---

### 3.2 Inventory Movement Types

**Movement Types:**

| Type | From Location | To Location | Trigger | Impact |
| --- | --- | --- | --- | --- |
| Stock Inward | External (PO) | Warehouse | Purchase Order | Increase warehouse stock |
| Stock Adjustment | N/A | Warehouse/DP | Manual adjustment | Increase/decrease stock |
| Transfer | Warehouse | Warehouse | Manual | Move stock between warehouses |
| Depletion | Warehouse | Distribution Point | Approved depletion plan dispatch | Decrease warehouse, increase DP |
| Order Dispatch | Distribution Point | Outlet | Order dispatch by DP | Decrease DP stock |
| Order Delivery | N/A | N/A | LSR delivery confirmation | Log only (outlet stock not tracked) |
| Event Handover | Warehouse | External (Event Supplier) | Delivery note handover | Decrease warehouse stock |
| Event Return | External (Event Supplier) | Warehouse | Return note validation | Increase warehouse stock |

**Movement Transaction Rules:**

- **Atomic:** Each movement is a single database transaction
- **Cannot negative stock:** Validation check before movement
- **Audit trail:** Every movement logged in `inventory_movements` table
- **Reference tracking:** Link to originating entity (order, shipment, etc.)

---

### 3.3 Stock Inward Logic

**Triggered By:**

- Admin manual entry (Purchase Order received)

**Required Data:**

- Warehouse ID
- Product ID
- Quantity (must be > 0)
- Unit Cost (for weighted average cost calculation)
- PO Number (reference)
- Received Date

**Processing Logic:**

```
1. Validate product exists and is active
2. Validate warehouse exists and is active
3. Validate quantity > 0
4. Update inventory_locations:
   - Increase quantity by received quantity
   - Recalculate weighted average unit_cost:
     new_cost = (old_qty * old_cost + new_qty * new_cost) / (old_qty + new_qty)
5. Insert record into inventory_movements (type: stock_inward)
6. Log audit trail
```

**Weighted Average Cost Example:**

- **Existing stock:** 100 units @ LKR 150 each = LKR 15,000
- **New stock:** 50 units @ LKR 180 each = LKR 9,000
- **Total:** 150 units @ LKR 160 each = LKR 24,000
- **New weighted avg:** LKR 160.00

---

### 3.4 Stock Adjustment Logic

**Triggered By:**

- Admin manual entry (cycle count, damage, expiry, etc.)

**Adjustment Types:**

- **Increase:** Add stock (e.g., found during count)
- **Decrease:** Remove stock (e.g., damage, expiry, theft)

**Required Data:**

- Location Type + Location ID
- Product ID
- Adjustment Quantity (positive for increase, negative for decrease)
- Reason (mandatory, from predefined list or free text)
- Performed By (admin user)

**Reason Codes:**

- Cycle Count Adjustment
- Damaged Goods
- Expired Stock
- Theft/Loss
- Found Stock
- Data Correction
- Other (requires explanation)

**Processing Logic:**

```
1. Validate product and location exist
2. If decrease: Validate sufficient available stock (not reserved)
   - Cannot adjust if: quantity - reserved_quantity < adjustment_amount
3. Update inventory_locations:
   - Increase/decrease quantity
   - Do NOT adjust reserved_quantity
4. Insert record into inventory_movements (type: stock_adjustment)
5. Log audit trail with reason
6. Send notification to SM if adjustment > 10% of stock or value > LKR 50,000
```

**Validation:**

- **Cannot reduce stock below reserved quantity**
- **Cannot negative stock:** Available stock after adjustment must be ≥ 0

---

### 3.5 Stock Transfer Logic

**Triggered By:**

- Admin manual entry (inter-warehouse transfer)

**Required Data:**

- Source Warehouse ID
- Destination Warehouse ID
- Product ID
- Transfer Quantity (must be > 0)
- Transfer Date
- Transfer Reason (optional)

**Validation:**

- **Source ≠ Destination:** Cannot transfer to same warehouse
- **Sufficient stock:** Source must have available stock ≥ transfer quantity
- **Both locations active**

**Processing Logic:**

```
1. Validate source has sufficient available stock
2. Begin transaction:
   a. Decrease inventory_locations for source
   b. Increase inventory_locations for destination
   c. Insert TWO records into inventory_movements:
      - Movement OUT from source (quantity: -X)
      - Movement IN to destination (quantity: +X)
3. Commit transaction
4. Log audit trail
5. Generate transfer document PDF (optional)
```

**Transfer Document:**

- Source warehouse details
- Destination warehouse details
- Transfer number (auto-generated)
- Product list with quantities
- Transfer date
- Authorized by (admin user)

---

### 3.6 Stock Reservation Logic (Depletion Plans)

**Triggered By:**

- SM approval of depletion plan

**Processing Logic:**

```
When depletion plan is approved:
1. For each item in depletion plan:
   a. Validate warehouse has sufficient available stock
   b. Update inventory_locations:
      - Do NOT change quantity
      - Increase reserved_quantity by approved_quantity
2. Update depletion plan status to "ready_to_deplete"
3. Generate shipments per market/distribution point
```

**Reserved Stock Rules:**

- **Reserved stock** is NOT available for new orders
- **Available for Orders = Total Quantity - Reserved Quantity**
- **Reserved until:** Shipment is dispatched from warehouse
- **On dispatch:** Reserved quantity → 0, Total quantity decreases

**Reservation Release:**

- **If depletion plan rejected:** Release ALL reserved stock for that plan
- **If shipment dispatched:** Release reserved stock, decrease total stock

---

### 3.7 Low Stock Alerts

**Trigger Conditions:**

- **Available stock ≤ Reorder Level** for a product at a location
- **Check frequency:** Daily at 9:00 AM

**Alert Recipients:**

- System Admin (always)
- Coordinator for that warehouse (if assigned)

**Alert Content:**

- Product name + SKU
- Location name
- Current available stock
- Reorder level
- Recommended reorder quantity = (Reorder Level * 2) - Available Stock

**Alert Suppression:**

- **No duplicate alerts** within 7 days for same product + location
- **Dismiss alert** when stock replenished above reorder level

---

<a name="locations"></a>

## 4. Location Management Logic

### 4.1 Warehouse Management

**Creation Rules:**

**Required Fields:**

- Warehouse Name
- Warehouse Code (unique, alphanumeric + dash, uppercase)
- Address

**Optional Fields:**

- Contact Person
- Contact Phone
- Contact Email
- Status (defaults to Active)

**Validation:**

-