# Laravel POS System - Comprehensive Documentation

## Table of Contents
1. [Sales Flow](#sales-flow)
2. [Payment Types](#payment-types)
3. [Report Generation](#report-generation)
4. [User Roles & Permissions](#user-roles--permissions)
5. [Key Models & Relationships](#key-models--relationships)
6. [Dashboard & Navigation](#dashboard--navigation)
7. [Important Business Logic](#important-business-logic)

---

## 1. Sales Flow (POS → Order Completion)

### Entry Point
- **Route**: `/pos/sales`
- **Controller**: `OrderController@sales`
- **Data Loaded**: Active products, customers, tax configs, opening balance, cashier name, M-Pesa config

### Process Flow
1. **Product Selection**
   - Search by name, SKU, or barcode
   - Scan barcode
   - Click product cards
   - Multiple price levels: `selling_price`, `price_2`, `price_3`

2. **Cart Management**
   - Add/remove items
   - Adjust quantities
   - Apply discounts (percentage or fixed amount)
   - View subtotal, tax, total

3. **Customer Selection** (Optional for cash, required for credit/partial)

4. **Payment Details**
   - **Payment Type**: `cash`, `credit`, `partial`
   - **Payment Methods**: JSON array of `{method, amount}` (cash, mpesa, card, etc.)
   - **Paid Amount**: Must cover total for cash; partial/credit allow lower amounts
   - **Due Date**: Required for credit sales

5. **Order Submission** (POST to `OrderController@store`)

### Order Processing (Database Transaction)
```
1. Validate items (product exists, qty > 0, price ≥ cost price)
2. Calculate subtotal (sum of price × qty for all items)
3. Apply discount (percentage or fixed)
4. Calculate tax via TaxConfig::calculateTax()
5. Determine total = (subtotal - discount) + tax
6. Set payment details based on payment_type
   - Cash: paid_amount ≥ total, calculate change
   - Credit: credit_amount = total, paid_amount = 0
   - Partial: credit_amount = total - paid_amount
7. Validate customer required for credit/partial
8. Generate invoice number: INV-YYYYMMDD-XXXXXX
9. Create Order record
10. Update customer balance if credit amount > 0
11. Create OrderItem for each product
12. Reduce product stock quantity
13. Create InventoryLog (type: stock_out)
14. Create EtimsInvoice if e-TIMS configured
15. Log activity via UserActivityLog
16. Commit transaction
```

### Order Status
- Status is set to `completed` immediately upon creation
- No pending or draft states

---

## 2. Payment Types

### Cash Payment
- **Characteristics**: Full payment at point of sale
- **Requirements**: `paid_amount` ≥ `total`
- **Calculations**: `change_amount = paid_amount - total`
- **Credit Status**: `null`

### Credit Payment
- **Characteristics**: Full amount owed, deferred payment
- **Requirements**: Customer required, due date optional
- **Calculations**: 
  - `credit_amount = total`
  - `paid_amount = 0`
- **Credit Status**: `pending`
- **Customer Impact**: Balance increased by credit amount

### Partial Payment
- **Characteristics**: Part paid now, part owed
- **Requirements**: Customer required
- **Calculations**:
  - `credit_amount = total - paid_amount`
  - If `credit_amount > 0`, status = `partial`
- **Customer Impact**: Balance increased by credit amount

### Payment Methods
1. **Primary Method**: Stored in `payment_method` field
2. **Multiple Methods**: Stored as JSON in `payment_methods` field
   ```json
   [
     {"method": "cash", "amount": 500.00},
     {"method": "mpesa", "amount": 300.00}
   ]
   ```
3. **Supported Methods**: `cash`, `mpesa`, `card`, `credit`, custom methods

### Credit Management
- **Recording Payments**: `CreditController@recordPayment`
- **Payment Updates**:
  - Creates `CreditPayment` record
  - Reduces `Customer.balance`
  - Updates `Order.credit_status` (`partial` → `paid` if fully paid)
- **Overdue Status**: `CreditController@updateOverdueStatus` marks orders past due date as `overdue`
- **Reminders**: Email/SMS via `CreditController@sendReminder`

---

## 3. Report Generation

### Sales Report (`/reports/sales`)
**Key Metrics**:
- Total sales amount
- Total number of orders
- Average order value
- Total cost and profit
- Payment method totals (cash, mpesa, card)
- Daily sales breakdown
- Per-order details (invoice, date, customer, cashier, amounts)

**Filters**: Date range, customer
**Export**: CSV

### Cashier Activity Report (`/reports/cashier`)
**Key Metrics**:
- User login/logout counts
- Auto-logout counts
- Sale counts per cashier
- Sales totals per cashier
- Profit per cashier
- Daily sales per cashier

**Filters**: Date range, user
**Export**: CSV

### Cashier Sales Report (`/reports/cashier-sales`)
**Key Metrics**:
- Detailed items sold per cashier
- Top 10 products sold
- Category breakdown
- Credit summary (sales, paid, pending, overdue)
- Per-cashier credit performance

**Filters**: Date range, user, category
**Export**: CSV

### Profit Report (`/reports/profit`)
**Key Metrics**:
- Revenue, cost, gross profit
- Net profit (after expenses)
- Top 10 products by revenue
- Category profits
- Daily sales trends
- Item-level profits

**Filters**: Date range
**Exports**: CSV, PDF

### Inventory Report (`/reports/inventory`)
**Key Metrics**:
- Total items in stock
- Total cost and retail value
- Low stock items (below threshold)
- Out-of-stock items
- Status per product (In Stock, Low Stock, Out of Stock)

**Filters**: None (shows all products)
**Export**: CSV

### Supplier Payments Report (`/reports/supplier-payments`)
**Key Metrics**:
- Payments to suppliers
- Stock-ins from suppliers
- Supplier summary (total ordered, total paid, balance)
- Payment method breakdown

**Filters**: Date range, supplier, payment method
**Export**: CSV

### Opening Balance Report (`/reports/opening-balance`)
**Key Metrics**:
- Opening balances per date
- Balances per user
- Total opening balance

**Filters**: Date range
**Export**: CSV

### Stock Movement Report (`/reports/stock-movement`)
**Key Metrics**:
- Combined view of inventory logs and sales
- Stock-in/out/adjustment movements
- Sale movements
- Movement summary totals
- Product-level movement details

**Filters**: Date range, product, category
**Export**: CSV

---

## 4. User Roles & Permissions

### Role Hierarchy
1. **Super Admin** (`super_admin`)
   - Full system access
   - Can manage all settings (M-Pesa, SMS, system, e-TIMS)
   - Cannot be edited/deleted by non-super admins
   - Can create other super admins

2. **Admin** (`admin`)
   - Can manage users (except super admins)
   - Can assign permissions
   - Full access to functional areas
   - Cannot modify system settings

3. **Cashier** (`cashier`)
   - Limited access based on permissions
   - Can process sales (if `pos.sales` permission)
   - Can view assigned reports
   - Permissions customizable by admin

### Permission System
- **Storage**: JSON array in `users.permissions` column
- **Check Method**: `$user->hasPermission('slug')`
- **Super Admin/Admin**: Always return `true` for any permission
- **Cashier**: Only returns `true` if permission exists in JSON array

### Key Permission Slugs
#### Dashboard & Sales
- `dashboard.view` - View dashboard
- `pos.sales` - Process POS sales

#### Products & Categories
- `products.view`, `products.create`, `products.edit`, `products.delete`
- `categories.view`, `categories.create`, `categories.edit`, `categories.delete`

#### Customers & Suppliers
- `customers.view`, `customers.create`, `customers.edit`, `customers.delete`
- `suppliers.view`, `suppliers.create`, `suppliers.edit`, `suppliers.delete`
- `suppliers.finance` - View supplier finance

#### Orders & Inventory
- `orders.view`, `orders.cancel`
- `inventory.view`, `inventory.stock-in`, `inventory.adjustment`

#### Reports
- `reports.view` - General report access
- `reports.sales`, `reports.profit`, `reports.inventory`
- `reports.supplier-payments`, `reports.opening-balance`
- `reports.stock-movement`, `reports.cashier`

#### Finance
- `expenses.view`, `expenses.create`, `expenses.delete`
- `expenses.cashflow` - View cash flow report
- `credit.view`, `credit.manage`, `credit.reminders`

#### Tax & M-Pesa
- `tax.view`, `tax.manage`
- `tax.etims.view`, `tax.etims.manage`
- `mpesa.view`, `mpesa.manage`

#### Settings
- `users.manage` - Manage users
- `permissions.manage` - Manage user permissions
- `settings.sms` - Manage SMS settings

### Default Permissions by Role
**Cashier** (typical defaults):
- `pos.sales`
- `orders.view`
- `customers.view`
- `reports.sales` (maybe)

**Admin**:
- All permissions except system settings

**Super Admin**:
- All permissions (implicit)

---

## 5. Key Models & Relationships

### Order Model
**Table**: `orders`
**Attributes**:
- `invoice_number` (string, unique)
- `user_id` (foreign ID)
- `customer_id` (foreign ID, nullable)
- `subtotal`, `discount`, `tax`, `total` (decimal)
- `paid_amount`, `change_amount` (decimal)
- `payment_method` (string)
- `payment_methods` (JSON)
- `payment_type` (enum: cash, credit, partial)
- `credit_amount`, `due_date`, `credit_status` (string)
- `status` (string: completed, cancelled)
- `tax_details` (JSON)
- `notes` (text)

**Relationships**:
- `belongsTo` User
- `belongsTo` Customer
- `hasMany` OrderItem
- `hasMany` CreditPayment

**Accessors**:
- `profit` - Calculated as total - sum of (product cost × quantity)
- `credit_balance` - credit_amount minus sum of credit payments

### OrderItem Model
**Table**: `order_items`
**Attributes**:
- `order_id`, `product_id` (foreign IDs)
- `product_name`, `product_sku` (string)
- `price`, `unit_cost`, `subtotal` (decimal)
- `price_type` (string: default, Price 2, Price 3)
- `quantity` (decimal)

**Relationships**:
- `belongsTo` Order
- `belongsTo` Product

### Product Model
**Table**: `products`
**Attributes**:
- `category_id` (foreign ID)
- `name`, `sku`, `barcode` (string)
- `image` (string, nullable)
- `cost_price`, `selling_price`, `price_2`, `price_3` (decimal)
- `price_2_name`, `price_3_name` (string)
- `stock_quantity`, `low_stock_threshold` (decimal)
- `is_active` (boolean)
- `description` (text, nullable)
- `expiry_date` (date, nullable)

**Relationships**:
- `belongsTo` Category
- `hasMany` OrderItem
- `hasMany` InventoryLog
- `hasMany` ProductPriceHistory

**Scopes**:
- `active` - Where `is_active = true`
- `lowStock` - Where `stock_quantity <= low_stock_threshold`
- `expired` - Where `expiry_date < now()`
- `expiringSoon` - Where expiring within X days

### Customer Model
**Table**: `customers`
**Attributes**:
- `name`, `phone`, `email`, `address` (string)
- `balance` (decimal)
- `is_active` (boolean)

**Relationships**:
- `hasMany` Order

### CreditPayment Model
**Table**: `credit_payments`
**Attributes**:
- `order_id`, `customer_id`, `user_id` (foreign IDs)
- `amount` (decimal)
- `balance_before`, `balance_after` (decimal)
- `payment_method` (string)
- `reference_number`, `notes` (string/text)

**Relationships**:
- `belongsTo` Order
- `belongsTo` Customer
- `belongsTo` User

### UserActivityLog Model
**Table**: `user_activity_logs`
**Attributes**:
- `user_id` (foreign ID)
- `activity_type` (string: login, sale, auto_logout, etc.)
- `description` (string, nullable)
- `ip_address`, `user_agent` (string)
- `metadata` (JSON)
- `client_time` (timestamp)

**Relationships**:
- `belongsTo` User

### InventoryLog Model
**Table**: `inventory_logs`
**Attributes**:
- `product_id`, `user_id`, `supplier_id` (foreign IDs)
- `type` (string: stock_in, stock_out, adjustment, opening_balance)
- `quantity`, `previous_stock`, `new_stock` (decimal)
- `unit_cost` (decimal, nullable)
- `reference_number`, `notes` (string)

**Relationships**:
- `belongsTo` Product
- `belongsTo` User
- `belongsTo` Supplier

### TaxConfig Model
**Table**: `tax_configs`
**Attributes**:
- `name`, `code` (string)
- `rate` (decimal)
- `is_active`, `is_default` (boolean)
- `type` (string: percentage, fixed)
- `description` (text)

**Methods**:
- `calculateTax($subtotal)` - Returns total tax and details array

### OpeningBalance Model
**Table**: `opening_balances`
**Attributes**:
- `user_id` (foreign ID)
- `date` (date)
- `amount` (decimal)
- `notes` (text)

**Relationships**:
- `belongsTo` User

---

## 6. Dashboard & Navigation

### Dashboard (`/dashboard`)
**Controller**: `DashboardController@index`

**Statistics Cards**:
1. **Today's Sales** - Sum of today's completed orders
2. **This Week** - Sum of last 7 days' sales
3. **This Month** - Sum of current month's sales
4. **Credit Outstanding** - Total unpaid credit amounts

**Alerts**:
- Low stock products (count)
- Overdue credit orders (count with "View" button)

**Widgets**:
1. **Recent Orders** - Last 10 orders with customer/cashier info
2. **Top Products** - Top 5 products by quantity sold (current month)
3. **Credit Summary** - Outstanding, recovered today/month, overdue count
4. **Overdue Orders** - First 5 overdue orders with customer details

**Quick Actions**:
- "New Sale" button → Redirects to POS

### Navigation Sidebar
**Conditional Display**: Based on user permissions (`$user->hasPermission()`)

#### Main Section
1. **Dashboard** (if `dashboard.view`)
2. **POS / Sales** (if `pos.sales`)
3. **Orders** (if `orders.view`)

#### Finance Section
1. **Opening Balance** (if `opening-balance.view`)
2. **Cash Flow** (if `expenses.cashflow`)
3. **Tax** (if `tax.view`)
4. **M-Pesa** (Super Admin only)
5. **Credit** (if `credit.view`)

#### Products Section
1. **Products** (if `products.view`)
2. **Categories** (if `categories.view`)
3. **Inventory** (if `inventory.view`)
4. **Stock In** (if `inventory.stock-in`)
5. **Price Adjustment** (if `inventory.adjustment`)
6. **Price History** (if `inventory.view`)
7. **Expiry Management** (if `inventory.view`)

#### People Section
1. **Customers** (if `customers.view`)
2. **Suppliers** (if `suppliers.view`)
3. **Supplier Finance** (if `suppliers.finance`)

#### Reports Section
1. **Cashier Sales** (if `reports.cashier-sales`)
2. **Cashier Activity** (if `reports.cashier`)
3. **Sales Report** (if `reports.sales`)
4. **Stock Movement** (if `reports.stock-movement`)
5. **Profit Report** (if `reports.profit`)
6. **Inventory Report** (if `reports.inventory`)
7. **Supplier Payments** (if `reports.supplier-payments`)

#### Settings Section
1. **Users** (if `users.manage`)
2. **SMS** (Super Admin only)
3. **Receipt & Reports** (Super Admin only)
4. **System Settings** (Super Admin only)

### Role-Based Navigation Differences
- **Cashier**: Minimal navigation (POS, maybe limited reports)
- **Admin**: All functional links except system settings
- **Super Admin**: Complete access including system settings

### Theme Support
- Light/Dark theme toggle
- User preference saved to database
- System-wide theme application

---

## 7. Important Business Logic

### Price Validation
- **Rule**: Selling price cannot be below cost price
- **Implementation**: Checked in `OrderController@store` for each item
- **Error**: Returns 422 with message: "Cannot sell [product] below buying price"

### Tax Calculation
- **Multiple Taxes**: Active taxes applied cumulatively
- **Calculation**: Each tax rate × subtotal (after discount)
- **Storage**: Details stored in `order.tax_details` JSON
- **Example**: 10% VAT + 2% Service tax = 12% total

### Stock Management
- **On Sale**: Stock reduced by ordered quantity
- **On Cancellation**: Stock restored, InventoryLog type = `stock_in`
- **Low Stock Alert**: When `stock_quantity <= low_stock_threshold`
- **Out of Stock**: When `stock_quantity <= 0`

### Credit System
- **Balance Tracking**: Customer balance = sum of all credit amounts - sum of all payments
- **Order Level**: Each order tracks its own credit balance
- **Overdue Detection**: Based on `due_date` and `credit_status`
- **Status Flow**: `pending` → `partial` → `paid` (or `overdue` if past due)

### Activity Logging
- **Login**: Recorded with IP and user agent
- **Sales**: Invoice number, total, items count
- **Auto-Logout**: Session expiration due to inactivity
- **Client Time**: JavaScript timestamp sent for accurate logging

### e-TIMS Integration
- **Condition**: Only if `EtimsConfig::isConfigured()` returns true
- **Invoice Creation**: Automatic for every order
- **Status**: Initially `pending`

### Inactivity Auto-Logout
- **Timeout**: Configurable (default 300 seconds)
- **Countdown Modal**: 30-second warning before logout
- **Activity Reset**: Mouse movement or keypress resets timer
- **Logging**: Auto-logout recorded in activity logs

### Discount System
- **Types**: Percentage or fixed amount
- **Application**: Applied to subtotal before tax
- **Maximum**: No validation (could be 100%)
- **Storage**: `discount_type` and `discount` (value) fields

### Invoice Number Format
- **Pattern**: `INV-YYYYMMDD-XXXXXX`
- **Example**: `INV-20260329-000123`
- **Sequence**: Incrementing counter per day (resets daily)

### Payment Methods Handling
- **Primary Method**: First method in array or `cash`
- **JSON Storage**: Flexible for multiple methods
- **Validation**: Total of method amounts must equal order total

---

## Additional Features

### Opening Balance
- **Purpose**: Record starting cash drawer amount
- **Frequency**: Daily per user
- **Reporting**: Included in cash flow reports

### Supplier Management
- **Stock In**: Record purchases from suppliers
- **Finance Tracking**: Supplier balance, payments
- **Integration**: Linked to inventory logs

### Expiry Management
- **Tracking**: Products with expiry dates
- **Alerts**: Products expiring soon
- **Actions**: Mark expired, extend, dispose

### SMS Integration
- **Configuration**: SMS gateway settings
- **Usage**: Credit reminders, system notifications
- **Testing**: SMS test functionality

### M-Pesa Integration
- **STK Push**: Initiate payment requests
- **Status Check**: Verify payment status
- **Manual Recording**: Record M-Pesa payments manually
- **Callback**: Handle M-Pesa callbacks

---

## System Architecture

### Frontend
- **Framework**: Blade templates with Bootstrap 5
- **JavaScript**: jQuery, AJAX for dynamic updates
- **Theme**: Light/dark mode support
- **Responsive**: Mobile-friendly sidebar

### Backend
- **Framework**: Laravel
- **Authentication**: Laravel built-in
- **Authorization**: Permission-based (JSON array)
- **Database**: MySQL/PostgreSQL
- **Queue**: Not used (synchronous)

### Security
- **CSRF Protection**: Enabled
- **SQL Injection**: Protected via Eloquent
- **XSS**: Blade escaping
- **Session Timeout**: Configurable inactivity logout

---

*Documentation generated for Laravel POS System - Version 2026.03.29*