Modules Documentation

Detailed documentation for each Decconz ERP module, including features, configuration, and usage.

Module Overview

Module Description Key Features License
Finance Complete accounting and financial management Invoicing, expenses, reports, budgets Included
Inventory Stock and warehouse management Stock tracking, orders, suppliers, barcode Included
Sales CRM Customer relationship management Leads, quotes, orders, pipeline Included
HR & Payroll Human resources management Employees, payroll, attendance, leaves Premium
Manufacturing Production and manufacturing management BOM, production orders, quality control Premium
Projects Project management and tracking Tasks, timelines, budgets, resources Premium

Finance Module

Configuration

Configuration File
// config/finance.php
return [
    'default_currency' => 'USD',
    'default_tax_rate' => 8.5,
    'invoice_prefix' => 'INV',
    'payment_terms' => [
        'net_15' => 'Net 15 Days',
        'net_30' => 'Net 30 Days',
        'due_on_receipt' => 'Due on Receipt'
    ],
    'chart_of_accounts' => [
        'assets' => [
            'current_assets' => ['cash', 'accounts_receivable'],
            'fixed_assets' => ['equipment', 'property']
        ],
        'liabilities' => [
            'current_liabilities' => ['accounts_payable'],
            'long_term_liabilities' => ['loans']
        ],
        'equity' => ['capital', 'retained_earnings'],
        'revenue' => ['sales', 'service_income'],
        'expenses' => ['salaries', 'rent', 'utilities']
    ]
];

Reports

Generate Financial Report
-- Balance Sheet Query
SELECT 
    a.account_code,
    a.account_name,
    a.account_type,
    COALESCE(SUM(je.debit), 0) - COALESCE(SUM(je.credit), 0) AS balance
FROM accounts a
LEFT JOIN journal_entries je ON a.id = je.account_id
WHERE je.entry_date BETWEEN '2024-01-01' AND '2024-01-31'
    AND a.account_type IN ('asset', 'liability', 'equity')
GROUP BY a.id, a.account_code, a.account_name, a.account_type
ORDER BY a.account_code;

-- Profit & Loss Query
SELECT 
    a.account_code,
    a.account_name,
    CASE 
        WHEN a.account_type = 'revenue' THEN 'Income'
        WHEN a.account_type = 'expense' THEN 'Expense'
    END AS category,
    COALESCE(SUM(CASE WHEN a.account_type = 'revenue' THEN je.credit 
                     WHEN a.account_type = 'expense' THEN je.debit END), 0) AS amount
FROM accounts a
LEFT JOIN journal_entries je ON a.id = je.account_id
WHERE je.entry_date BETWEEN '2024-01-01' AND '2024-01-31'
    AND a.account_type IN ('revenue', 'expense')
GROUP BY a.id, a.account_code, a.account_name, a.account_type
ORDER BY a.account_type, a.account_code;

Inventory Module

Stock Management

Stock Movement Logic
// InventoryService.php
class InventoryService {
    public function adjustStock($productId, $warehouseId, $quantity, $type, $reference = null) {
        // Get current stock
        $currentStock = $this->getCurrentStock($productId, $warehouseId);
        
        // Calculate new quantity
        if ($type === 'add') {
            $newQuantity = $currentStock + $quantity;
        } elseif ($type === 'subtract') {
            $newQuantity = $currentStock - $quantity;
            if ($newQuantity < 0) {
                throw new Exception('Insufficient stock');
            }
        } else {
            $newQuantity = $quantity;
        }
        
        // Update stock
        $this->updateStockRecord($productId, $warehouseId, $newQuantity);
        
        // Log transaction
        $this->logStockTransaction([
            'product_id' => $productId,
            'warehouse_id' => $warehouseId,
            'previous_quantity' => $currentStock,
            'new_quantity' => $newQuantity,
            'adjustment_type' => $type,
            'quantity' => $quantity,
            'reference' => $reference,
            'user_id' => Auth::id(),
            'timestamp' => now()
        ]);
        
        // Check reorder level
        $this->checkReorderLevel($productId, $warehouseId, $newQuantity);
        
        return $newQuantity;
    }
    
    private function checkReorderLevel($productId, $warehouseId, $currentQuantity) {
        $product = Product::with('reorderLevels')->find($productId);
        $reorderLevel = $product->reorderLevels->where('warehouse_id', $warehouseId)->first();
        
        if ($reorderLevel && $currentQuantity <= $reorderLevel->reorder_point) {
            $this->createPurchaseOrder($product, $reorderLevel->reorder_quantity);
        }
    }
}