From 43d7f86d90f2462228c7469b7b03712c20e0880a Mon Sep 17 00:00:00 2001 From: o-psi Date: Mon, 18 Dec 2023 17:34:11 +0000 Subject: [PATCH 01/31] Readable Password Ajax --- ajax.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ajax.php b/ajax.php index 991883f9..da6fee02 100644 --- a/ajax.php +++ b/ajax.php @@ -479,3 +479,7 @@ if (isset($_GET['get_totp_token_via_id'])) { mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Login', log_action = 'View TOTP', log_description = '$session_name viewed login TOTP code for $name', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_client_id = $client_id, log_user_id = $session_user_id, log_entity_id = $login_id"); } } + +if (isset($_GET['get_readable_pass'])) { + echo GenerateReadablePassword(4); +} From e0c8b0c30d20fa948d90c97843a11175cb9d4588 Mon Sep 17 00:00:00 2001 From: o-psi Date: Mon, 18 Dec 2023 17:34:22 +0000 Subject: [PATCH 02/31] Readable Password Function --- functions.php | 60 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/functions.php b/functions.php index b471d80b..36586536 100644 --- a/functions.php +++ b/functions.php @@ -15,8 +15,7 @@ use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; // Function to generate both crypto & URL safe random strings -function randomString($length = 16) -{ +function randomString($length = 16) { // Generate some cryptographically safe random bytes // Generate a little more than requested as we'll lose some later converting $random_bytes = random_bytes($length + 5); @@ -33,8 +32,7 @@ function randomString($length = 16) } // Older keygen function - only used for TOTP currently -function key32gen() -{ +function key32gen() { $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; $chars .= "234567"; while (1) { @@ -256,8 +254,7 @@ function setupFirstUserSpecificKey($user_password, $site_encryption_master_key) * New Users: Requires the admin setting up their account have a Specific/Session key configured * Password Changes: Will use the current info in the session. */ -function encryptUserSpecificKey($user_password) -{ +function encryptUserSpecificKey($user_password) { $iv = randomString(); $salt = randomString(); @@ -871,4 +868,55 @@ function calculateAccountBalance($mysqli, $account_id) { } return $balance; +} + +function generateReadablePassword($security_level) { + // Arrays of words + $adjectives = ['Smart', 'Swift', 'Secure', 'Stable', 'Digital', 'Virtual', 'Active', 'Dynamic', 'Innovative', 'Efficient', 'Portable', 'Wireless', 'Rapid', 'Intuitive', 'Automated', 'Robust', 'Reliable', 'Sleek', 'Modern', 'Happy', 'Funny', 'Quick', 'Bright', 'Clever', 'Gentle', 'Brave', 'Calm', 'Eager', 'Fierce', 'Kind', 'Lucky', 'Proud', 'Silly', 'Witty', 'Bold', 'Curious', 'Elated', 'Gracious', 'Honest', 'Jolly', 'Merry', 'Noble', 'Optimistic', 'Playful', 'Quirky', 'Rustic', 'Steady', 'Tranquil', 'Upbeat']; + $nouns = ['Computer', 'Laptop', 'Tablet', 'Server', 'Router', 'Software', 'Hardware', 'Pixel', 'Byte', 'App', 'Network', 'Cloud', 'Firewall', 'Email', 'Database', 'Folder', 'Document', 'Interface', 'Program', 'Gadget', 'Dinosaur', 'Tiger', 'Elephant', 'Kangaroo', 'Monkey', 'Unicorn', 'Dragon', 'Puppy', 'Kitten', 'Parrot', 'Lion', 'Bear', 'Fox', 'Wolf', 'Rabbit', 'Deer', 'Owl', 'Hedgehog', 'Turtle', 'Frog', 'Butterfly', 'Panda', 'Giraffe', 'Zebra', 'Peacock', 'Koala', 'Raccoon', 'Squirrel', 'Hippo', 'Rhino', 'Book', "Monitor"]; + $verbs = ['Connects', 'Runs', 'Processes', 'Secures', 'Encrypts', 'Saves', 'Updates', 'Boots', 'Scans', 'Compiles', 'Executes', 'Restores', 'Installs', 'Configures', 'Downloads', 'Streams', 'BacksUp', 'Syncs', 'Browses', 'Navigates', 'Runs', 'Jumps', 'Flies', 'Swims', 'Dances', 'Sings', 'Hops', 'Skips', 'Races', 'Climbs', 'Crawls', 'Glides', 'Twirls', 'Swings', 'Sprints', 'Gallops', 'Trots', 'Wanders', 'Strolls', 'Marches']; + $adverbs = ['Quickly', 'Slowly', 'Gracefully', 'Wildly', 'Loudly', 'Silently', 'Cheerfully', 'Eagerly', 'Gently', 'Happily', 'Jovially', 'Kindly', 'Lazily', 'Merrily', 'Neatly', 'Politely', 'Quietly', 'Rapidly', 'Smoothly', 'Tightly', 'Swiftly', 'Securely', 'Efficiently', 'Rapidly', 'Smoothly', 'Reliably', 'Safely', 'Wirelessly', 'Instantly', 'Silently', 'Automatically', 'Seamlessly', 'Digitally', 'Virtually', 'Continuously', 'Regularly', 'Intelligently', 'Logically']; + + // Randomly select words from arrays + $adj = $adjectives[array_rand($adjectives)]; + $noun = $nouns[array_rand($nouns)]; + $verb = $verbs[array_rand($verbs)]; + $adv = $adverbs[array_rand($adverbs)]; + + + + // Combine to create a base password + if ($security_level > 2 ) { + $password = "The" . $adj . $noun . $adv . $verb; + } else { + $password = $adj . $noun . $verb; + } + + // Mapping of letters to special characters and numbers + $mappings = [ + 'A' => '@', 'a' => '@', + 'E' => '3', 'e' => '3', + 'I' => '!', 'i' => '!', + 'O' => '0', 'o' => '0', + 'S' => '$', 's' => '$' + ]; + + // Replace characters based on mappings + if ($security_level > 4) { + $password = strtr($password, $mappings); + } else { + // Randomly replace characters based on mappings + for ($i = 0; $i < strlen($password); $i++) { + if (array_key_exists($password[$i], $mappings) && rand(0, 1)) { + $password[$i] = $mappings[$password[$i]]; + } + } + } + + if ($security_level > 3) { + // Add a random number at the end + $password .= rand(0, 99); + } + + return $password; } \ No newline at end of file From f0567c1fb7ec25d641dcb5401af88cd74ed2c45b Mon Sep 17 00:00:00 2001 From: o-psi Date: Mon, 18 Dec 2023 17:34:39 +0000 Subject: [PATCH 03/31] add password generation functionality --- client_contact_add_modal.php | 60 ++++++++++++----------- client_contact_details.php | 24 ++++++++++ client_contact_edit_modal.php | 90 +++++++++++++++++++++-------------- 3 files changed, 110 insertions(+), 64 deletions(-) diff --git a/client_contact_add_modal.php b/client_contact_add_modal.php index b7c8cf7c..b3762c2b 100644 --- a/client_contact_add_modal.php +++ b/client_contact_add_modal.php @@ -124,7 +124,7 @@ while ($row = mysqli_fetch_array($sql)) { $location_id = intval($row['location_id']); $location_name = nullable_htmlentities($row['location_name']); - ?> + ?> @@ -137,7 +137,7 @@
- +
@@ -145,7 +145,7 @@
- +
@@ -153,7 +153,7 @@
- +
@@ -183,36 +183,40 @@
- -
-
- -
-
- + +
+
+ +
+
+ +
+
-
-
- - diff --git a/client_contact_details.php b/client_contact_details.php index 45b79986..17687d6a 100644 --- a/client_contact_details.php +++ b/client_contact_details.php @@ -574,6 +574,30 @@ if (isset($_GET['contact_id'])) { diff --git a/client_logins.php b/client_logins.php index dc1ddf21..a7030acc 100644 --- a/client_logins.php +++ b/client_logins.php @@ -50,7 +50,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
- +
@@ -67,107 +69,110 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
- "> - - - - - - - - - + "> + + + + + + + + + - "; - } - $login_username = nullable_htmlentities(decryptLoginEntry($row['login_username'])); - if (empty($login_username)) { - $login_username_display = "-"; - } else { - $login_username_display = "$login_username"; - } - $login_password = nullable_htmlentities(decryptLoginEntry($row['login_password'])); - $login_otp_secret = nullable_htmlentities($row['login_otp_secret']); - $login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"'; - if (empty($login_otp_secret)) { - $otp_display = "-"; - } else { - $otp_display = " Hover.."; - } - $login_note = nullable_htmlentities($row['login_note']); - $login_important = intval($row['login_important']); - $login_contact_id = intval($row['login_contact_id']); - $login_vendor_id = intval($row['login_vendor_id']); - $login_asset_id = intval($row['login_asset_id']); - $login_software_id = intval($row['login_software_id']); + while ($row = mysqli_fetch_array($sql)) { + $login_id = intval($row['login_id']); + $login_name = nullable_htmlentities($row['login_name']); + $login_description = nullable_htmlentities($row['login_description']); + if (empty($login_description)) { + $login_description_display = "-"; + } else { + $login_description_display = $login_description; + } + $login_uri = nullable_htmlentities($row['login_uri']); + if (empty($login_uri)) { + $login_uri_display = "-"; + } else { + $login_uri_display = "$login_uri"; + } + $login_username = nullable_htmlentities(decryptLoginEntry($row['login_username'])); + if (empty($login_username)) { + $login_username_display = "-"; + } else { + $login_username_display = "$login_username"; + } + $login_password = nullable_htmlentities(decryptLoginEntry($row['login_password'])); + $login_otp_secret = nullable_htmlentities($row['login_otp_secret']); + $login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"'; + if (empty($login_otp_secret)) { + $otp_display = "-"; + } else { + $otp_display = " Hover.."; + } + $login_note = nullable_htmlentities($row['login_note']); + $login_important = intval($row['login_important']); + $login_contact_id = intval($row['login_contact_id']); + $login_vendor_id = intval($row['login_vendor_id']); + $login_asset_id = intval($row['login_asset_id']); + $login_software_id = intval($row['login_software_id']); ?> - "> - - - - - - - "> + + + + + + + - + + + ?>
NameDescriptionUsernamePasswordOTPURIAction
NameDescriptionUsernamePasswordOTPURIAction
- - - - - - - -
+ + + + + + + + - -
+ ?>
@@ -176,8 +181,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); function showOTP(id, secret) { //Send a GET request to ajax.php as ajax.php?get_totp_token=true&totp_secret=SECRET jQuery.get( - "ajax.php", - {get_totp_token: 'true', totp_secret: secret}, + "ajax.php", { + get_totp_token: 'true', + totp_secret: secret + }, function(data) { //If we get a response from post.php, parse it as JSON const token = JSON.parse(data); @@ -191,8 +198,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); function showOTPViaLoginID(login_id) { // Send a GET request to ajax.php as ajax.php?get_totp_token_via_id=true&login_id=ID jQuery.get( - "ajax.php", - {get_totp_token_via_id: 'true', login_id: login_id}, + "ajax.php", { + get_totp_token_via_id: 'true', + login_id: login_id + }, function(data) { //If we get a response from post.php, parse it as JSON const token = JSON.parse(data); @@ -204,7 +213,24 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); } function generatePassword() { - document.getElementById("password").value = "" + document.getElementById("password").value = "" + } + + function generatePassword() { + var url = '/ajax.php?get_readable_pass=true'; + + // Make an AJAX request to the server + var xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var password = xhr.responseText; + + document.getElementById("password").value = password; + } + }; + xhr.send(); } @@ -219,4 +245,3 @@ require_once "client_login_import_modal.php"; require_once "client_login_export_modal.php"; require_once "footer.php"; - From f1516b06ee7a9ba8244a3c73e7b9c24a4145dd6e Mon Sep 17 00:00:00 2001 From: o-psi Date: Thu, 21 Dec 2023 14:37:19 +0000 Subject: [PATCH 05/31] Refactor calculateInvoiceBalance function to sanitizr This commit refactors the calculateInvoiceBalance function in functions.php. The invoice_id parameter is now properly sanitized using intval() to prevent SQL injection attacks. Additionally, the SQL query for retrieving the invoice and payments data has been formatted for better readability. --- functions.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/functions.php b/functions.php index 958ff24b..cc5c5b45 100644 --- a/functions.php +++ b/functions.php @@ -892,12 +892,17 @@ function addToMailQueue($mysqli, $data) { } function calculateInvoiceBalance($mysqli, $invoice_id) { - $sql_invoice = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_id = $invoice_id"); + $invoice_id_int = intval($invoice_id); + $sql_invoice = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_id = $invoice_id_int"); $row = mysqli_fetch_array($sql_invoice); $invoice_amount = floatval($row['invoice_amount']); - $invoice_id = intval($row['invoice_id']); - $sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS total_payments FROM payments WHERE payment_invoice_id = $invoice_id"); + $sql_payments = mysqli_query( + $mysqli, + "SELECT SUM(payment_amount) AS total_payments FROM payments + WHERE payment_invoice_id = $invoice_id + "); + $row = mysqli_fetch_array($sql_payments); $total_payments = floatval($row['total_payments']); From 3eaaf7374453d418a3f88d5da352dd2bd38bd7c0 Mon Sep 17 00:00:00 2001 From: o-psi Date: Thu, 21 Dec 2023 17:10:15 +0000 Subject: [PATCH 06/31] Add more billable status functionality --- client_statement.php | 2 +- client_tickets.php | 14 ++++++++++++ post/ticket.php | 32 ++++++++++++++++++++++++++ ticket.php | 17 ++++++++++++++ ticket_edit_billable_modal.php | 42 ++++++++++++++++++++++++++++++++++ ticket_edit_modal.php | 2 +- tickets.php | 16 +++++++++++++ 7 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 ticket_edit_billable_modal.php diff --git a/client_statement.php b/client_statement.php index fa166620..c58eabdb 100644 --- a/client_statement.php +++ b/client_statement.php @@ -1,7 +1,7 @@ Number Subject Contact + Billable Priority Status Assigned @@ -117,6 +119,7 @@ $total_tickets_closed = intval($row['total_tickets_closed']); $ticket_subject = nullable_htmlentities($row['ticket_subject']); $ticket_priority = nullable_htmlentities($row['ticket_priority']); $ticket_status = nullable_htmlentities($row['ticket_status']); + $ticket_billable = intval($row['ticket_billable']); $ticket_vendor_ticket_number = nullable_htmlentities($row['ticket_vendor_ticket_number']); $ticket_created_at = nullable_htmlentities($row['ticket_created_at']); $ticket_created_at_time_ago = timeAgo($row['ticket_created_at']); @@ -195,6 +198,15 @@ $total_tickets_closed = intval($row['total_tickets_closed']); + + + $"; + } else { + echo "X"; + } + ?> @@ -217,6 +229,8 @@ $total_tickets_closed = intval($row['total_tickets_closed']); require "ticket_edit_contact_modal.php"; + require "ticket_edit_billable_modal.php"; + } } diff --git a/post/ticket.php b/post/ticket.php index 59370566..892c636b 100644 --- a/post/ticket.php +++ b/post/ticket.php @@ -1097,3 +1097,35 @@ if (isset($_POST['bulk_delete_scheduled_tickets'])) { header("Location: " . $_SERVER["HTTP_REFERER"]); } + +if(isset($_POST['set_billable_status'])) { + + validateTechRole(); + + $ticket_id = intval($_POST['ticket_id']); + $billable_status = sanitizeInput($_POST['billable_status']); + + mysqli_query($mysqli, + "UPDATE tickets SET + ticket_billable = '$billable_status' + WHERE ticket_id = $ticket_id" + ); + + //Logging + mysqli_query( + $mysqli, + "INSERT INTO logs SET + log_type = 'Ticket', + log_action = 'Modify', + log_description = '$session_name modified ticket billable status', + log_ip = '$session_ip', + log_user_agent = '$session_user_agent', + log_user_id = $session_user_id, + log_entity_id = $ticket_id" + ); + + $_SESSION['alert_message'] = "Ticket billable status updated"; + + header("Location: " . $_SERVER["HTTP_REFERER"]); + +} \ No newline at end of file diff --git a/ticket.php b/ticket.php index c65bfd30..1179fb99 100644 --- a/ticket.php +++ b/ticket.php @@ -637,6 +637,21 @@ if (isset($_GET['ticket_id'])) { Total time worked:
+ + + +
@@ -851,6 +866,8 @@ if (isset($_GET['ticket_id'])) { require_once "ticket_invoice_add_modal.php"; + require_once "ticket_edit_billable_modal.php"; + } diff --git a/ticket_edit_billable_modal.php b/ticket_edit_billable_modal.php new file mode 100644 index 00000000..2a9bb030 --- /dev/null +++ b/ticket_edit_billable_modal.php @@ -0,0 +1,42 @@ + diff --git a/ticket_edit_modal.php b/ticket_edit_modal.php index d486c44d..63e35c14 100644 --- a/ticket_edit_modal.php +++ b/ticket_edit_modal.php @@ -68,7 +68,7 @@
- diff --git a/tickets.php b/tickets.php index e369638e..5952d80b 100644 --- a/tickets.php +++ b/tickets.php @@ -1,5 +1,6 @@ Client / Contact + Billable + Priority @@ -277,6 +281,7 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']); $ticket_subject = nullable_htmlentities($row['ticket_subject']); $ticket_priority = nullable_htmlentities($row['ticket_priority']); $ticket_status = nullable_htmlentities($row['ticket_status']); + $ticket_billable = intval($row['ticket_billable']); $ticket_vendor_ticket_number = nullable_htmlentities($row['ticket_vendor_ticket_number']); $ticket_created_at = nullable_htmlentities($row['ticket_created_at']); $ticket_created_at_time_ago = timeAgo($row['ticket_created_at']); @@ -356,6 +361,15 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']);
+ + + $"; + } else { + echo "X"; + } + ?> @@ -376,6 +390,8 @@ $user_active_assigned_tickets = intval($row['total_tickets_assigned']); require "ticket_edit_priority_modal.php"; + require "ticket_edit_billable_modal.php"; + } } From e639b69db9401173047c232f845562939fdd9bf3 Mon Sep 17 00:00:00 2001 From: johnnyq Date: Thu, 21 Dec 2023 13:03:37 -0500 Subject: [PATCH 07/31] Merged All Dashboards into 1 allow you to toggle between show financial and show technical --- dashboard.php | 1136 ++++++++++++++++++++++++++++++++++++++- dashboard_financial.php | 1128 -------------------------------------- dashboard_nav.php | 11 - dashboard_technical.php | 187 ------- side_nav.php | 2 +- 5 files changed, 1134 insertions(+), 1330 deletions(-) delete mode 100644 dashboard_financial.php delete mode 100644 dashboard_nav.php delete mode 100644 dashboard_technical.php diff --git a/dashboard.php b/dashboard.php index 0472e88f..63794698 100644 --- a/dashboard.php +++ b/dashboard.php @@ -1,7 +1,1137 @@ + +
+ + + + +
+ > + +
+ + + = 2 && $config_module_enable_ticketing == 1) { ?> +
+ > + +
+ + +
+ +window.location.href = \'dashboard_technical.php\';'); +} + +//Define var so it doesnt throw errors in logs +$largest_income_month = 0; + +//Get Total income +$sql_total_payments_to_invoices = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS total_payments_to_invoices FROM payments WHERE YEAR(payment_date) = $year"); +$row = mysqli_fetch_array($sql_total_payments_to_invoices); +$total_payments_to_invoices = floatval($row['total_payments_to_invoices']); +//Do not grab transfer payment as these have a category_id of 0 +$sql_total_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS total_revenues FROM revenues WHERE YEAR(revenue_date) = $year AND revenue_category_id > 0"); +$row = mysqli_fetch_array($sql_total_revenues); +$total_revenues = floatval($row['total_revenues']); + +$total_income = $total_payments_to_invoices + $total_revenues; + +//Get Total expenses and do not grab transfer expenses as these have a vendor of 0 +$sql_total_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS total_expenses FROM expenses WHERE expense_vendor_id > 0 AND YEAR(expense_date) = $year"); +$row = mysqli_fetch_array($sql_total_expenses); +$total_expenses = floatval($row['total_expenses']); + +//Total up all the Invoices that are not draft or cancelled +$sql_invoice_totals = mysqli_query($mysqli, "SELECT SUM(invoice_amount) AS invoice_totals FROM invoices WHERE invoice_status NOT LIKE 'Draft' AND invoice_status NOT LIKE 'Cancelled' AND YEAR(invoice_date) = $year"); +$row = mysqli_fetch_array($sql_invoice_totals); +$invoice_totals = floatval($row['invoice_totals']); + +//Quaeries from Receivables +$sql_total_payments_to_invoices_all_years = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS total_payments_to_invoices_all_years FROM payments"); +$row = mysqli_fetch_array($sql_total_payments_to_invoices_all_years); +$total_payments_to_invoices_all_years = floatval($row['total_payments_to_invoices_all_years']); + +$sql_invoice_totals_all_years = mysqli_query($mysqli, "SELECT SUM(invoice_amount) AS invoice_totals_all_years FROM invoices WHERE invoice_status NOT LIKE 'Draft' AND invoice_status NOT LIKE 'Cancelled'"); +$row = mysqli_fetch_array($sql_invoice_totals_all_years); +$invoice_totals_all_years = floatval($row['invoice_totals_all_years']); + +$receivables = $invoice_totals_all_years - $total_payments_to_invoices_all_years; + +$profit = $total_income - $total_expenses; + +$sql_accounts = mysqli_query($mysqli, "SELECT * FROM accounts WHERE account_archived_at IS NULL ORDER BY account_name ASC"); + +$sql_latest_invoice_payments = mysqli_query( + $mysqli, + "SELECT * FROM payments, invoices, clients + WHERE payment_invoice_id = invoice_id + AND invoice_client_id = client_id + ORDER BY payment_id DESC LIMIT 5" +); + +$sql_latest_expenses = mysqli_query( + $mysqli, + "SELECT * FROM expenses, vendors, categories + WHERE expense_vendor_id = vendor_id + AND expense_category_id = category_id + ORDER BY expense_id DESC LIMIT 5" +); + +//Get Yearly Recurring Income Total +$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_yearly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'year' AND YEAR(recurring_created_at) <= $year"); +$row = mysqli_fetch_array($sql_recurring_yearly_total); +$recurring_yearly_total = floatval($row['recurring_yearly_total']); + +//Get Monthly Recurring Income Total +$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_monthly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'month' AND YEAR(recurring_created_at) <= $year"); +$row = mysqli_fetch_array($sql_recurring_monthly_total); +$recurring_monthly_total = floatval($row['recurring_monthly_total']) + ($recurring_yearly_total / 12); + +//Get Yearly Recurring Expenses Total +$sql_recurring_expense_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_expense_amount) AS recurring_expense_yearly_total FROM recurring_expenses WHERE recurring_expense_status = 1 AND recurring_expense_frequency = 2 AND YEAR(recurring_expense_created_at) <= $year"); +$row = mysqli_fetch_array($sql_recurring_expense_yearly_total); +$recurring_expense_yearly_total = floatval($row['recurring_expense_yearly_total']); + +//Get Monthly Recurring Expenses Total +$sql_recurring_expense_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_expense_amount) AS recurring_expense_monthly_total FROM recurring_expenses WHERE recurring_expense_status = 1 AND recurring_expense_frequency = 1 AND YEAR(recurring_expense_created_at) <= $year"); +$row = mysqli_fetch_array($sql_recurring_expense_monthly_total); +$recurring_expense_monthly_total = floatval($row['recurring_expense_monthly_total']) + ($recurring_expense_yearly_total / 12); + +//Get Total Miles Driven +$sql_miles_driven = mysqli_query($mysqli, "SELECT SUM(trip_miles) AS total_miles FROM trips WHERE YEAR(trip_date) = $year"); +$row = mysqli_fetch_array($sql_miles_driven); +$total_miles = floatval($row['total_miles']); + +//Get Total Recurring Invoices added +$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_id') AS recurring_invoices_added FROM recurring WHERE YEAR(recurring_created_at) = $year")); +$recurring_invoices_added = intval($row['recurring_invoices_added']); + +//Get Total Clients added +$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('client_id') AS clients_added FROM clients WHERE YEAR(client_created_at) = $year AND client_archived_at IS NULL")); +$clients_added = intval($row['clients_added']); + +//Get Total Vendors added +$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('vendor_id') AS vendors_added FROM vendors WHERE YEAR(vendor_created_at) = $year AND vendor_client_id = 0 AND vendor_template = 0 AND vendor_archived_at IS NULL")); +$vendors_added = intval($row['vendors_added']); + +?> + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+

Cash Flow

+
+ + + + +
+
+
+ +
+
+
+ +
+
+
+

Income by Category (Top 5)

+
+ +
+
+
+ +
+
+
+ +
+
+
+

Expenses by Category (Top 5)

+
+ +
+
+
+ +
+
+
+ +
+
+
+

Expenses by Vendor (Top 5)

+
+ +
+
+
+ +
+
+
+ +
+
+
+

Account Balances

+
+ +
+
+
+ + + + + + + + + + + +
+
+
+
+
+
+
+

Latest Income

+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + +
DateCustomerInvoiceAmount
+
+
+
+
+
+
+

Latest Expenses

+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + +
DateVendorCategoryAmount
+
+
+
+
+
+
+

Trip Flow

+
+ + + + +
+
+
+ +
+
+
+
+ + + + + + CURRENT_DATE + AND domain_expire < CURRENT_DATE + INTERVAL 30 DAY + AND domain_archived_at IS NULL" +)); +$expiring_domains = $sql_domains_expiring['expiring_domains']; + +// Expiring Certificates (but not ones that have already expired) +$sql_certs_expiring = mysqli_fetch_assoc(mysqli_query( + $mysqli, + "SELECT COUNT('certificate_id') as expiring_certs + FROM certificates + WHERE certificate_expire IS NOT NULL + AND certificate_expire > CURRENT_DATE + AND certificate_expire < CURRENT_DATE + INTERVAL 30 DAY + AND certificate_archived_at IS NULL" +)); +$expiring_certificates = $sql_certs_expiring['expiring_certs']; + +?> + + + + + + + + + + + diff --git a/dashboard_financial.php b/dashboard_financial.php deleted file mode 100644 index 2cd0c00f..00000000 --- a/dashboard_financial.php +++ /dev/null @@ -1,1128 +0,0 @@ -window.location.href = \'dashboard_technical.php\';'); -} - -if (isset($_GET['year'])) { - $year = intval($_GET['year']); -} else { - $year = date('Y'); -} - -//GET unique years from expenses, payments invoices and revenues -$sql_years_select = mysqli_query( - $mysqli, - "SELECT YEAR(expense_date) AS all_years FROM expenses - UNION DISTINCT SELECT YEAR(payment_date) FROM payments - UNION DISTINCT SELECT YEAR(revenue_date) FROM revenues - UNION DISTINCT SELECT YEAR(invoice_date) FROM invoices - ORDER BY all_years DESC -"); - -?> - -
- - - -
- > - -
- -
- > - -
- -
- - 0"); -$row = mysqli_fetch_array($sql_total_revenues); -$total_revenues = floatval($row['total_revenues']); - -$total_income = $total_payments_to_invoices + $total_revenues; - -//Get Total expenses and do not grab transfer expenses as these have a vendor of 0 -$sql_total_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS total_expenses FROM expenses WHERE expense_vendor_id > 0 AND YEAR(expense_date) = $year"); -$row = mysqli_fetch_array($sql_total_expenses); -$total_expenses = floatval($row['total_expenses']); - -//Total up all the Invoices that are not draft or cancelled -$sql_invoice_totals = mysqli_query($mysqli, "SELECT SUM(invoice_amount) AS invoice_totals FROM invoices WHERE invoice_status NOT LIKE 'Draft' AND invoice_status NOT LIKE 'Cancelled' AND YEAR(invoice_date) = $year"); -$row = mysqli_fetch_array($sql_invoice_totals); -$invoice_totals = floatval($row['invoice_totals']); - -//Quaeries from Receivables -$sql_total_payments_to_invoices_all_years = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS total_payments_to_invoices_all_years FROM payments"); -$row = mysqli_fetch_array($sql_total_payments_to_invoices_all_years); -$total_payments_to_invoices_all_years = floatval($row['total_payments_to_invoices_all_years']); - -$sql_invoice_totals_all_years = mysqli_query($mysqli, "SELECT SUM(invoice_amount) AS invoice_totals_all_years FROM invoices WHERE invoice_status NOT LIKE 'Draft' AND invoice_status NOT LIKE 'Cancelled'"); -$row = mysqli_fetch_array($sql_invoice_totals_all_years); -$invoice_totals_all_years = floatval($row['invoice_totals_all_years']); - -$receivables = $invoice_totals_all_years - $total_payments_to_invoices_all_years; - -$profit = $total_income - $total_expenses; - -$sql_accounts = mysqli_query($mysqli, "SELECT * FROM accounts WHERE account_archived_at IS NULL ORDER BY account_name ASC"); - -$sql_latest_invoice_payments = mysqli_query( - $mysqli, - "SELECT * FROM payments, invoices, clients - WHERE payment_invoice_id = invoice_id - AND invoice_client_id = client_id - ORDER BY payment_id DESC LIMIT 5" -); - -$sql_latest_expenses = mysqli_query( - $mysqli, - "SELECT * FROM expenses, vendors, categories - WHERE expense_vendor_id = vendor_id - AND expense_category_id = category_id - ORDER BY expense_id DESC LIMIT 5" -); - -//Get Yearly Recurring Income Total -$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_yearly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'year' AND YEAR(recurring_created_at) <= $year"); -$row = mysqli_fetch_array($sql_recurring_yearly_total); -$recurring_yearly_total = floatval($row['recurring_yearly_total']); - -//Get Monthly Recurring Income Total -$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_amount) AS recurring_monthly_total FROM recurring WHERE recurring_status = 1 AND recurring_frequency = 'month' AND YEAR(recurring_created_at) <= $year"); -$row = mysqli_fetch_array($sql_recurring_monthly_total); -$recurring_monthly_total = floatval($row['recurring_monthly_total']) + ($recurring_yearly_total / 12); - -//Get Yearly Recurring Expenses Total -$sql_recurring_expense_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_expense_amount) AS recurring_expense_yearly_total FROM recurring_expenses WHERE recurring_expense_status = 1 AND recurring_expense_frequency = 2 AND YEAR(recurring_expense_created_at) <= $year"); -$row = mysqli_fetch_array($sql_recurring_expense_yearly_total); -$recurring_expense_yearly_total = floatval($row['recurring_expense_yearly_total']); - -//Get Monthly Recurring Expenses Total -$sql_recurring_expense_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_expense_amount) AS recurring_expense_monthly_total FROM recurring_expenses WHERE recurring_expense_status = 1 AND recurring_expense_frequency = 1 AND YEAR(recurring_expense_created_at) <= $year"); -$row = mysqli_fetch_array($sql_recurring_expense_monthly_total); -$recurring_expense_monthly_total = floatval($row['recurring_expense_monthly_total']) + ($recurring_expense_yearly_total / 12); - -//Get Total Miles Driven -$sql_miles_driven = mysqli_query($mysqli, "SELECT SUM(trip_miles) AS total_miles FROM trips WHERE YEAR(trip_date) = $year"); -$row = mysqli_fetch_array($sql_miles_driven); -$total_miles = floatval($row['total_miles']); - -//Get Total Recurring Invoices added -$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('recurring_id') AS recurring_invoices_added FROM recurring WHERE YEAR(recurring_created_at) = $year")); -$recurring_invoices_added = intval($row['recurring_invoices_added']); - -//Get Total Clients added -$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('client_id') AS clients_added FROM clients WHERE YEAR(client_created_at) = $year AND client_archived_at IS NULL")); -$clients_added = intval($row['clients_added']); - -//Get Total Vendors added -$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('vendor_id') AS vendors_added FROM vendors WHERE YEAR(vendor_created_at) = $year AND vendor_client_id = 0 AND vendor_template = 0 AND vendor_archived_at IS NULL")); -$vendors_added = intval($row['vendors_added']); - -?> - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-

Cash Flow

-
- - - - -
-
-
- -
-
-
- -
-
-
-

Income by Category (Top 5)

-
- -
-
-
- -
-
-
- -
-
-
-

Expenses by Category (Top 5)

-
- -
-
-
- -
-
-
- -
-
-
-

Expenses by Vendor (Top 5)

-
- -
-
-
- -
-
-
- -
-
-
-

Account Balances

-
- -
-
-
- - - - - - - - - - - -
-
-
-
-
-
-
-

Latest Income

-
- -
-
-
- - - - - - - - - - - - - - - - - - - -
DateCustomerInvoiceAmount
-
-
-
-
-
-
-

Latest Expenses

-
- -
-
-
- - - - - - - - - - - - - - - - - - - -
DateVendorCategoryAmount
-
-
-
-
-
-
-

Trip Flow

-
- - - - -
-
-
- -
-
-
-
- - - - - - CURRENT_DATE - AND domain_expire < CURRENT_DATE + INTERVAL 30 DAY - AND domain_archived_at IS NULL" -)); -$expiring_domains = $sql_domains_expiring['expiring_domains']; - -// Expiring Certificates (but not ones that have already expired) -$sql_certs_expiring = mysqli_fetch_assoc(mysqli_query( - $mysqli, - "SELECT COUNT('certificate_id') as expiring_certs - FROM certificates - WHERE certificate_expire IS NOT NULL - AND certificate_expire > CURRENT_DATE - AND certificate_expire < CURRENT_DATE + INTERVAL 30 DAY - AND certificate_archived_at IS NULL" -)); -$expiring_certificates = $sql_certs_expiring['expiring_certs']; - -?> - - - - - - - - - - - diff --git a/dashboard_nav.php b/dashboard_nav.php deleted file mode 100644 index 22a4b5a4..00000000 --- a/dashboard_nav.php +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/dashboard_technical.php b/dashboard_technical.php deleted file mode 100644 index 5213600c..00000000 --- a/dashboard_technical.php +++ /dev/null @@ -1,187 +0,0 @@ - CURRENT_DATE - AND domain_expire < CURRENT_DATE + INTERVAL 30 DAY - AND domain_archived_at IS NULL" -)); -$expiring_domains = $sql_domains_expiring['expiring_domains']; - -// Expiring Certificates (but not ones that have already expired) -$sql_certs_expiring = mysqli_fetch_assoc(mysqli_query( - $mysqli, - "SELECT COUNT('certificate_id') as expiring_certs - FROM certificates - WHERE certificate_expire IS NOT NULL - AND certificate_expire > CURRENT_DATE - AND certificate_expire < CURRENT_DATE + INTERVAL 30 DAY - AND certificate_archived_at IS NULL" -)); -$expiring_certificates = $sql_certs_expiring['expiring_certs']; - -?> - -
- -
- - - - -