prepare("SELECT id FROM company_settings WHERE setting_key = ?"); $stmt->execute([$key]); if ($stmt->fetch()) { $stmt = $pdo->prepare("UPDATE company_settings SET setting_value = ?, updated_by = ?, updated_at = NOW() WHERE setting_key = ?"); $stmt->execute([$value, $_SESSION['admin_id'], $key]); } else { $stmt = $pdo->prepare("INSERT INTO company_settings (setting_key, setting_value, updated_by, updated_at) VALUES (?, ?, ?, NOW())"); $stmt->execute([$key, $value, $_SESSION['admin_id']]); } } logActivity($_SESSION['admin_id'], 'update_pricing', 'Updated base pricing configuration', 'settings'); $success = 'Pricing configuration saved successfully!'; } catch (Exception $e) { error_log("Pricing save error: " . $e->getMessage()); $error = 'Error saving pricing: ' . $e->getMessage(); } } // Load current pricing values $pricing = []; try { $pdo = getDBConnection(); $stmt = $pdo->query("SELECT setting_key, setting_value, updated_at FROM company_settings WHERE setting_key LIKE 'pricing_%'"); while ($row = $stmt->fetch()) { $pricing[$row['setting_key']] = $row['setting_value']; $pricing[$row['setting_key'] . '_updated'] = $row['updated_at']; } } catch (Exception $e) { error_log("Pricing load error: " . $e->getMessage()); } // Helper to get pricing value function pv($key, $default = '') { global $pricing; return htmlspecialchars($pricing[$key] ?? $default); } // Get last updated time $last_updated = null; foreach ($pricing as $k => $v) { if (str_ends_with($k, '_updated') && $v) { if (!$last_updated || $v > $last_updated) { $last_updated = $v; } } } // === CSV Export (must run before any HTML output) === if ($tab === 'invoices' && isset($_GET['inv_export']) && $_GET['inv_export'] === 'csv') { $csvStatus=$_GET['inv_status']??''; $csvClient=$_GET['inv_client']??''; $csvDateFrom=$_GET['inv_from']??''; $csvDateTo=$_GET['inv_to']??''; $csvSearch=trim($_GET['inv_search']??''); $csvCurrency=$_GET['inv_currency']??''; $csvDueFrom=$_GET['inv_due_from']??''; $csvDueTo=$_GET['inv_due_to']??''; $csvSort=$_GET['inv_sort']??'invoice_date'; $csvDir=($_GET['inv_dir']??'desc')==='asc'?'ASC':'DESC'; $csvAllowed=['invoice_number','invoice_date','due_date','total_amount','status','project_code','client_name']; if (!in_array($csvSort,$csvAllowed)) $csvSort='invoice_date'; $csvWhere=["1=1"]; $csvParams=[]; if($csvStatus){$csvWhere[]="i.status=?";$csvParams[]=$csvStatus;} if($csvClient){$csvWhere[]="i.client_id=?";$csvParams[]=(int)$csvClient;} if($csvCurrency){$csvWhere[]="i.currency=?";$csvParams[]=$csvCurrency;} if($csvDateFrom){$csvWhere[]="i.invoice_date>=?";$csvParams[]=$csvDateFrom;} if($csvDateTo){$csvWhere[]="i.invoice_date<=?";$csvParams[]=$csvDateTo;} if($csvDueFrom){$csvWhere[]="i.due_date>=?";$csvParams[]=$csvDueFrom;} if($csvDueTo){$csvWhere[]="i.due_date<=?";$csvParams[]=$csvDueTo;} if($csvSearch){$csvWhere[]="(i.invoice_number LIKE ? OR p.project_name LIKE ? OR i.project_code LIKE ? OR c.company_name LIKE ?)";$s="%$csvSearch%";$csvParams=array_merge($csvParams,[$s,$s,$s,$s]);} $csvWc=implode(' AND ',$csvWhere); $stmt=$pdo->prepare("SELECT i.*,p.project_name,p.industry,c.company_name as client_company,c.contact_person FROM invoices i INNER JOIN projects p ON i.project_id=p.id INNER JOIN clients c ON i.client_id=c.id WHERE $csvWc ORDER BY $csvSort $csvDir"); $stmt->execute($csvParams); header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename="invoices_'.date('Y-m-d_His').'.csv"'); $out=fopen('php://output','w'); fprintf($out,chr(0xEF).chr(0xBB).chr(0xBF)); fputcsv($out,['Invoice #','Client','Contact','Project','Project ID','Industry','Currency','Completes','Avg LOI','Rate/Sample','Total Amount','Invoice Date','Due Date','Paid Date','Status','Payment Ref','Remarks']); foreach($stmt->fetchAll(PDO::FETCH_ASSOC) as $r){ fputcsv($out,[$r['invoice_number'],$r['client_company'],$r['contact_person'],$r['project_name'],$r['project_code'],$r['industry'],$r['currency'],$r['valid_completes'],$r['avg_loi_minutes'],$r['rate_per_sample'],$r['total_amount'],$r['invoice_date'],$r['due_date'],$r['paid_date']??'',$r['status'],$r['payment_reference']??'',$r['remarks']??'']); } fclose($out);exit; } include 'includes/header.php'; ?>
Manage pricing, invoices & financial settings
Test your pricing by entering an LOI. Uses the saved rates above and live exchange rates.
No invoices found. Invoices are auto-generated when projects are closed.
| Invoice # | Client | Project | Curr | N | Total | Invoiced | Due | Status | Actions |
|---|---|---|---|---|---|---|---|---|---|
| 📄 |
* All amounts are inclusive of applicable taxes