Moved admin_ to /admin, user_ to user report_ to /reports each have their own post includes modals directories created seperate headers and footer. Also did the same for xcustom, more work to me done
This commit is contained in:
107
reports/budget.php
Normal file
107
reports/budget.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_expense_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(expense_date) AS expense_year FROM expenses WHERE expense_category_id > 0 ORDER BY expense_year DESC");
|
||||
|
||||
$categories = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Expense' ORDER BY category_name ASC");
|
||||
$monthlyTotals = array_fill(1, 12, 0); // Initialize monthly totals for each month
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-balance-scale mr-2"></i>Annual Budget</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_expense_years)) {
|
||||
$expense_year = $row['expense_year'];
|
||||
?>
|
||||
<option <?php if ($year == $expense_year) { ?> selected <?php } ?> > <?php echo $expense_year; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<canvas id="cashFlow" width="100%" height="20"></canvas>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead class="text-dark">
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th class="text-right">January</th>
|
||||
<th class="text-right">February</th>
|
||||
<th class="text-right">March</th>
|
||||
<th class="text-right">April</th>
|
||||
<th class="text-right">May</th>
|
||||
<th class="text-right">June</th>
|
||||
<th class="text-right">July</th>
|
||||
<th class="text-right">August</th>
|
||||
<th class="text-right">September</th>
|
||||
<th class="text-right">October</th>
|
||||
<th class="text-right">November</th>
|
||||
<th class="text-right">December</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if ($categories->num_rows > 0) {
|
||||
while($category = $categories->fetch_assoc()) {
|
||||
echo "<tr>";
|
||||
echo "<td>" . nullable_htmlentities($category['category_name']) . "</td>";
|
||||
$categoryTotal = 0;
|
||||
for ($month = 1; $month <= 12; $month++) {
|
||||
// Fetch the monthly budget for this category for 2022
|
||||
$sql = "SELECT budget_amount FROM budget WHERE budget_category_id = " . $category['category_id'] . " AND budget_month = $month AND budget_year = $year";
|
||||
$result = $mysqli->query($sql);
|
||||
if ($result->num_rows > 0) {
|
||||
$budget = $result->fetch_assoc();
|
||||
$amount = $budget['budget_amount'];
|
||||
$categoryTotal += $amount;
|
||||
$monthlyTotals[$month] += $amount;
|
||||
echo "<td class='text-right'>" . $amount . "</td>";
|
||||
} else {
|
||||
echo "<td class='text-right'>0</td>";
|
||||
}
|
||||
}
|
||||
echo "<td class='text-right'>" . $categoryTotal . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
// Displaying the monthly totals row
|
||||
echo "<tr><td><strong>Total</strong></td>";
|
||||
$grandTotal = 0;
|
||||
for ($month = 1; $month <= 12; $month++) {
|
||||
$grandTotal += $monthlyTotals[$month];
|
||||
echo "<td class='text-right'>" . $monthlyTotals[$month] . "</td>";
|
||||
}
|
||||
echo "<td class='text-right'>" . $grandTotal . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
?>
|
||||
85
reports/clients_with_balance.php
Normal file
85
reports/clients_with_balance.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-exclamation-triangle mr-2"></i>Clients with a Balance</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<?php
|
||||
$sql_clients = mysqli_query($mysqli, "
|
||||
SELECT
|
||||
clients.client_id,
|
||||
clients.client_name,
|
||||
IFNULL(SUM(invoices.invoice_amount), 0) - IFNULL(SUM(payments.payment_amount), 0) AS balance
|
||||
FROM
|
||||
clients
|
||||
LEFT JOIN
|
||||
invoices
|
||||
ON
|
||||
clients.client_id = invoices.invoice_client_id
|
||||
AND invoices.invoice_status != 'Draft'
|
||||
AND invoices.invoice_status != 'Cancelled'
|
||||
AND invoice_status != 'Non-Billable'
|
||||
LEFT JOIN
|
||||
(SELECT
|
||||
payment_invoice_id,
|
||||
SUM(payment_amount) as payment_amount
|
||||
FROM payments
|
||||
GROUP BY payment_invoice_id) as payments
|
||||
ON
|
||||
invoices.invoice_id = payments.payment_invoice_id
|
||||
GROUP BY
|
||||
clients.client_id,
|
||||
clients.client_name
|
||||
HAVING
|
||||
balance > 0
|
||||
ORDER BY
|
||||
balance DESC
|
||||
");
|
||||
|
||||
?>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Balance</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_clients)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$balance = floatval($row['balance']);
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><a href="invoices.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $balance, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
|
||||
75
reports/credential_rotation.php
Normal file
75
reports/credential_rotation.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_credential');
|
||||
|
||||
// TODO: Default to 90 but allow input field to change this
|
||||
if (isset($_GET['days'])) {
|
||||
$days = intval($_GET['days']);
|
||||
} else {
|
||||
$days = 90;
|
||||
}
|
||||
|
||||
$passwords_not_rotated_sql = mysqli_query($mysqli,
|
||||
"SELECT credential_id, credential_name, credential_description, credential_password_changed_at, credential_client_id, client_id, client_name
|
||||
FROM credentials
|
||||
LEFT JOIN clients ON credential_client_id = client_id
|
||||
WHERE DATE(credential_password_changed_at) < DATE_SUB(CURDATE(), INTERVAL $days DAY)
|
||||
ORDER BY client_name"
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Client credentials not changed/rotated in the last 90 days</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Credential Name</th>
|
||||
<th class="text-right">Credential Description</th>
|
||||
<th class="text-right">Credential Password Last Changed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($passwords_not_rotated_sql)) {
|
||||
|
||||
$credential_id = intval($row['credential_id']);
|
||||
$credential_name = nullable_htmlentities($row['credential_name']);
|
||||
$credential_description = nullable_htmlentities($row['credential_description']);
|
||||
$credential_password_changed = nullable_htmlentities($row['credential_password_changed_at']);
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $client_name; ?></td>
|
||||
<td class="text-right"><?php echo $credential_name; ?></td>
|
||||
<td class="text-right"><?php echo $credential_description; ?></td>
|
||||
<td class="text-right"><?php echo timeAgo($credential_password_changed) . " (" . $credential_password_changed . ")" ?></td>
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
|
||||
97
reports/expense_by_vendor.php
Normal file
97
reports/expense_by_vendor.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
if ($_GET['year'] === 'all') {
|
||||
$year = 'all';
|
||||
} else {
|
||||
$year = intval($_GET['year']);
|
||||
}
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_payment_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(payment_date) AS payment_year FROM payments
|
||||
UNION SELECT DISTINCT YEAR(revenue_date) AS payment_year FROM revenues
|
||||
ORDER BY payment_year DESC"
|
||||
);
|
||||
|
||||
$year_condition = ($year == 'all') ? "" : "AND YEAR(expense_date) = $year";
|
||||
|
||||
$sql_vendor_expenses = mysqli_query($mysqli, "
|
||||
SELECT
|
||||
vendors.*,
|
||||
SUM(expenses.expense_amount) AS amount_paid
|
||||
FROM
|
||||
vendors
|
||||
LEFT JOIN
|
||||
expenses ON vendors.vendor_id = expenses.expense_vendor_id $year_condition
|
||||
GROUP BY
|
||||
vendors.vendor_id
|
||||
HAVING
|
||||
amount_paid > 599
|
||||
ORDER BY
|
||||
amount_paid DESC
|
||||
");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-building mr-2"></i>Expense By Vendor <small>(With expense amounts of 600 or more)</small></h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<option value="all" <?php if ($year == 'all') { ?> selected <?php } ?> >All Years</option>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_payment_years)) {
|
||||
$payment_year = intval($row['payment_year']);
|
||||
?>
|
||||
<option <?php if ($year == $payment_year) { ?> selected <?php } ?> > <?php echo $payment_year; ?></option>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Vendor</th>
|
||||
<th class="text-right">Paid</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_vendor_expenses)) {
|
||||
$vendor_id = intval($row['vendor_id']);
|
||||
$vendor_name = nullable_htmlentities($row['vendor_name']);
|
||||
$amount_paid = floatval($row['amount_paid']); ?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $vendor_name; ?></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $amount_paid, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
?>
|
||||
193
reports/expense_summary.php
Normal file
193
reports/expense_summary.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_expense_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(expense_date) AS expense_year FROM expenses WHERE expense_category_id > 0 ORDER BY expense_year DESC");
|
||||
|
||||
$sql_categories = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Expense' ORDER BY category_name ASC");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-coins mr-2"></i>Expense Summary</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_expense_years)) {
|
||||
$expense_year = $row['expense_year'];
|
||||
?>
|
||||
<option <?php if ($year == $expense_year) { ?> selected <?php } ?> > <?php echo $expense_year; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<canvas id="cashFlow" width="100%" height="20"></canvas>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead class="text-dark">
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th class="text-right">January</th>
|
||||
<th class="text-right">February</th>
|
||||
<th class="text-right">March</th>
|
||||
<th class="text-right">April</th>
|
||||
<th class="text-right">May</th>
|
||||
<th class="text-right">June</th>
|
||||
<th class="text-right">July</th>
|
||||
<th class="text-right">August</th>
|
||||
<th class="text-right">September</th>
|
||||
<th class="text-right">October</th>
|
||||
<th class="text-right">November</th>
|
||||
<th class="text-right">December</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_categories)) {
|
||||
$category_id = intval($row['category_id']);
|
||||
$category_name = nullable_htmlentities($row['category_name']);
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $category_name; ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$total_expense_for_all_months = 0;
|
||||
for ($month = 1; $month<=12; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_amount_for_month FROM expenses WHERE expense_category_id = $category_id AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_amount_for_month = floatval($row['expense_amount_for_month']);
|
||||
$total_expense_for_all_months = $expense_amount_for_month + $total_expense_for_all_months;
|
||||
|
||||
|
||||
?>
|
||||
<td class="text-right"><a class="text-dark" href="expenses.php?q=<?php echo $category_name; ?>&dtf=<?php echo "$year-$month"; ?>-01&dtt=<?php echo "$year-$month"; ?>-31"><?php echo numfmt_format_currency($currency_format, $expense_amount_for_month, $session_company_currency); ?></a></td>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<th class="text-right"><a class="text-dark" href="expenses.php?q=<?php echo $category_name; ?>&dtf=<?php echo $year; ?>-01-01&dtt=<?php echo $year; ?>-12-31"><?php echo numfmt_format_currency($currency_format, $total_expense_for_all_months, $session_company_currency); ?></a></th>
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<?php
|
||||
|
||||
for ($month = 1; $month<=12; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_total_amount_for_month FROM expenses WHERE YEAR(expense_date) = $year AND MONTH(expense_date) = $month AND expense_vendor_id > 0");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_total_amount_for_month = floatval($row['expense_total_amount_for_month']);
|
||||
$total_expense_for_all_months = $expense_total_amount_for_month + $total_expense_for_all_months;
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><a class="text-dark" href="expenses.php?dtf=<?php echo "$year-$month"; ?>-01&dtt=<?php echo "$year-$month"; ?>-31"><?php echo numfmt_format_currency($currency_format, $expense_total_amount_for_month, $session_company_currency); ?></a></th>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<th class="text-right"><a class="text-dark" href="expenses.php?dtf=<?php echo $year; ?>-01-01&dtt=<?php echo $year; ?>-12-31"><?php echo numfmt_format_currency($currency_format, $total_expense_for_all_months, $session_company_currency); ?></th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
?>
|
||||
|
||||
<script>
|
||||
// Set new default font family and font color to mimic Bootstrap's default styling
|
||||
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
|
||||
Chart.defaults.global.defaultFontColor = '#292b2c';
|
||||
|
||||
var ctx = document.getElementById("cashFlow");
|
||||
var myLineChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||
datasets: [{
|
||||
label: "Expense",
|
||||
lineTension: 0.3,
|
||||
fill: false,
|
||||
borderColor: "#dc3545",
|
||||
pointBackgroundColor: "#dc3545",
|
||||
pointBorderColor: "#dc3545",
|
||||
pointHoverRadius: 5,
|
||||
pointHoverBackgroundColor: "#dc3545",
|
||||
pointHitRadius: 50,
|
||||
pointBorderWidth: 2,
|
||||
data: [
|
||||
<?php
|
||||
|
||||
$largest_expense_month = 0;
|
||||
|
||||
for ($month = 1; $month<=12; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_amount_for_month FROM expenses WHERE YEAR(expense_date) = $year AND MONTH(expense_date) = $month AND expense_vendor_id > 0");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expenses_for_month = floatval($row['expense_amount_for_month']);
|
||||
|
||||
if ($expenses_for_month > 0 && $expenses_for_month > $largest_expense_month) {
|
||||
$largest_expense_month = $expenses_for_month;
|
||||
}
|
||||
|
||||
echo "$expenses_for_month,";
|
||||
|
||||
} ?>
|
||||
|
||||
],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
time: {
|
||||
unit: 'date'
|
||||
},
|
||||
gridLines: {
|
||||
display: false
|
||||
},
|
||||
ticks: {
|
||||
maxTicksLimit: 12
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 0,
|
||||
max: <?php $max = max(1000, $largest_expense_month, $largest_income_month, $largest_invoice_month); echo roundUpToNearestMultiple($max); ?>,
|
||||
maxTicksLimit: 5
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, .125)",
|
||||
}
|
||||
}],
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
53
reports/includes/footer.php
Normal file
53
reports/includes/footer.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
require_once "../includes/inc_confirm_modal.php";
|
||||
?>
|
||||
|
||||
<?php
|
||||
if (str_contains(basename($_SERVER["PHP_SELF"]), "admin_")) { ?>
|
||||
<p class="text-right font-weight-light">ITFlow <?php echo APP_VERSION ?> · <a target="_blank" href="https://docs.itflow.org">Docs</a> · <a target="_blank" href="https://forum.itflow.org">Forum</a> · <a target="_blank" href="https://services.itflow.org">Services</a></p>
|
||||
<br>
|
||||
<?php } ?>
|
||||
|
||||
</div><!-- /.container-fluid -->
|
||||
</div> <!-- /.content -->
|
||||
</div> <!-- /.content-wrapper -->
|
||||
</div> <!-- ./wrapper -->
|
||||
|
||||
<!-- Set the browser window title to the clients name -->
|
||||
<script>document.title = <?php echo json_encode("$tab_title - $page_title"); ?>;</script>
|
||||
|
||||
<!-- REQUIRED SCRIPTS -->
|
||||
|
||||
<!-- Bootstrap 4 -->
|
||||
<script src="../plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<!-- Custom js-->
|
||||
<script src="../plugins/moment/moment.min.js"></script>
|
||||
<script src="../plugins/chart.js/Chart.min.js"></script>
|
||||
<script src="../plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>
|
||||
<script src='../plugins/daterangepicker/daterangepicker.js'></script>
|
||||
<script src='../plugins/select2/js/select2.min.js'></script>
|
||||
<script src='../plugins/inputmask/jquery.inputmask.min.js'></script>
|
||||
<script src="../plugins/tinymce/tinymce.min.js" referrerpolicy="origin"></script>
|
||||
<script src="../plugins/Show-Hide-Passwords-Bootstrap-4/bootstrap-show-password.min.js"></script>
|
||||
<script src="../plugins/clipboardjs/clipboard.min.js"></script>
|
||||
<script src="../js/keepalive.js"></script>
|
||||
<script src="../plugins/DataTables/datatables.min.js"></script>
|
||||
<script src="../plugins/intl-tel-input/js/intlTelInput.min.js"></script>
|
||||
|
||||
<!-- AdminLTE App -->
|
||||
<script src="../plugins/adminlte/js/adminlte.min.js"></script>
|
||||
<script src="../js/app.js"></script>
|
||||
<script src="../js/ajax_modal.js"></script>
|
||||
<script src="../js/confirm_modal.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<?php
|
||||
|
||||
// Calculate Execution time Uncomment for test
|
||||
|
||||
//$time_end = microtime(true);
|
||||
//$execution_time = ($time_end - $time_start);
|
||||
//echo '<h2>Total Execution Time: '.number_format((float) $execution_time, 10) .' seconds</h2>';
|
||||
54
reports/includes/header.php
Normal file
54
reports/includes/header.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
// Calculate Execution time start
|
||||
// uncomment for test
|
||||
// $time_start = microtime(true);
|
||||
|
||||
header("X-Frame-Options: DENY");
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="robots" content="noindex">
|
||||
|
||||
<title><?php echo $session_company_name; ?></title>
|
||||
|
||||
<!--
|
||||
Favicon
|
||||
If Fav Icon exists else use the default one
|
||||
-->
|
||||
<?php if(file_exists('../uploads/favicon.ico')) { ?>
|
||||
<link rel="icon" type="image/x-icon" href="/uploads/favicon.ico">
|
||||
<?php } ?>
|
||||
|
||||
<!-- Font Awesome Icons -->
|
||||
<link rel="stylesheet" href="../plugins/fontawesome-free/css/all.min.css">
|
||||
|
||||
<!-- Custom Style Sheet -->
|
||||
<link href="../plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../plugins/select2/css/select2.min.css" rel="stylesheet" type="text/css">
|
||||
<link href="../plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css" rel="stylesheet" type="text/css">
|
||||
<link href='../plugins/daterangepicker/daterangepicker.css' rel='stylesheet' />
|
||||
<link href="../plugins/toastr/toastr.min.css" rel="stylesheet">
|
||||
<link href="../plugins/DataTables/datatables.min.css" rel="stylesheet">
|
||||
<link href="../plugins/intl-tel-input/css/intlTelInput.min.css" rel="stylesheet">
|
||||
<!-- CSS to allow regular button to show as block button in mobile response view using the class btn-responsive -->
|
||||
<link href="../css/itflow_custom.css" rel="stylesheet">
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="../plugins/adminlte/css/adminlte.min.css">
|
||||
<!-- jQuery -->
|
||||
<script src="../plugins/jquery/jquery.min.js"></script>
|
||||
<script src="../plugins/toastr/toastr.min.js"></script>
|
||||
|
||||
</head>
|
||||
<body class="
|
||||
hold-transition sidebar-mini layout-fixed layout-navbar-fixed
|
||||
accent-<?php if (isset($_GET['client_id'])) { echo "blue"; } else { echo nullable_htmlentities($config_theme); } ?>
|
||||
<?php if ($config_theme_dark) { echo "dark-mode"; } ?>
|
||||
">
|
||||
<div class="wrapper text-sm">
|
||||
19
reports/includes/inc_all_reports.php
Normal file
19
reports/includes/inc_all_reports.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
require_once "../config.php";
|
||||
require_once "../functions.php";
|
||||
require_once "../includes/check_login.php";
|
||||
require_once "../includes/page_title.php";
|
||||
// Reporting Perms
|
||||
enforceUserPermission('module_reporting');
|
||||
require_once "includes/header.php";
|
||||
require_once "../includes/top_nav.php";
|
||||
require_once "includes/side_nav.php";
|
||||
require_once "../includes/inc_wrapper.php";
|
||||
require_once "../includes/inc_alert_feedback.php";
|
||||
require_once "../includes/filter_header.php";
|
||||
|
||||
// Set variable default values
|
||||
$largest_income_month = 0;
|
||||
$largest_invoice_month = 0;
|
||||
$recurring_total = 0;
|
||||
9
reports/includes/modal_footer.php
Normal file
9
reports/includes/modal_footer.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<script src="js/app.js"></script>
|
||||
<script src="plugins/Show-Hide-Passwords-Bootstrap-4/bootstrap-show-password.min.js"></script>
|
||||
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
|
||||
// Return the title and content as a JSON response
|
||||
echo json_encode(['content' => $content]);
|
||||
?>
|
||||
13
reports/includes/modal_header.php
Normal file
13
reports/includes/modal_header.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
require_once "../../../config.php";
|
||||
require_once "../../../functions.php";
|
||||
require_once "../../../includes/check_login.php";
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Check for the 'id' parameter
|
||||
//if (!isset($_GET['id'])) {
|
||||
// echo json_encode(['error' => 'ID missing.']);
|
||||
// exit;
|
||||
//}
|
||||
127
reports/includes/side_nav.php
Normal file
127
reports/includes/side_nav.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-dark-primary d-print-none">
|
||||
|
||||
<a class="pb-1 mt-1 brand-link" href="../">
|
||||
<p class="h5"><i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
|
||||
<span class="brand-text ">Back | <strong>Reports</strong>
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
|
||||
<!-- Sidebar Menu -->
|
||||
<nav>
|
||||
|
||||
<ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" data-accordion="false">
|
||||
|
||||
<li class="nav-header">FINANCIAL</li>
|
||||
<?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_financial") >= 1) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="income_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "income_summary.php") { echo "active"; } ?>">
|
||||
<i class="far fa-circle nav-icon"></i>
|
||||
<p>Income</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="income_by_client.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "income_by_client.php") { echo "active"; } ?>">
|
||||
<i class="far fa-user nav-icon"></i>
|
||||
<p>Income By Client</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="recurring_by_client.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_by_client.php") { echo "active"; } ?>">
|
||||
<i class="fa fa-sync nav-icon"></i>
|
||||
<p>Recurring Income By Client</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="clients_with_balance.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "clients_with_balance.php") { echo "active"; } ?>">
|
||||
<i class="fa fa-exclamation-triangle nav-icon"></i>
|
||||
<p>Clients with a Balance</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="expense_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expense_summary.php") { echo "active"; } ?>">
|
||||
<i class="far fa-credit-card nav-icon"></i>
|
||||
<p>Expense</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="expense_by_vendor.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expense_by_vendor.php") { echo "active"; } ?>">
|
||||
<i class="far fa-building nav-icon"></i>
|
||||
<p>Expense By Vendor</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="budget.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "budget.php") { echo "active"; } ?>">
|
||||
<i class="fas fa-list nav-icon"></i>
|
||||
<p>Budget</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="tax_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tax_summary.php") { echo "active"; } ?>">
|
||||
<i class="fas fa-percent nav-icon"></i>
|
||||
<p>Tax Summary</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="profit_loss.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "profit_loss.php") { echo "active"; } ?>">
|
||||
<i class="fas fa-file-invoice-dollar nav-icon"></i>
|
||||
<p>Profit & Loss</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="tickets_unbilled.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets_unbilled.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-life-ring"></i>
|
||||
<p>Unbilled Tickets</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php } // End financial reports IF statement ?>
|
||||
|
||||
|
||||
<li class="nav-header">TECHNICAL</li>
|
||||
<?php if ($config_module_enable_ticketing && lookupUserPermission("module_support") >= 1) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="ticket_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "ticket_summary.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-life-ring"></i>
|
||||
<p>Tickets</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="ticket_by_client.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "ticket_by_client.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-life-ring"></i>
|
||||
<p>Tickets by Client</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="time_by_tech.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "time_by_tech.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-life-ring"></i>
|
||||
<p>Time by Technician</p>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
<?php if (lookupUserPermission("module_credential") >= 1) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="credential_rotation.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "credential_rotation.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-key"></i>
|
||||
<p>Credential rotation</p>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
<!-- /.sidebar-menu -->
|
||||
|
||||
<div class="sidebar-custom mb-3">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.sidebar -->
|
||||
</aside>
|
||||
95
reports/income_by_client.php
Normal file
95
reports/income_by_client.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
if ($_GET['year'] === 'all') {
|
||||
$year = 'all';
|
||||
} else {
|
||||
$year = intval($_GET['year']);
|
||||
}
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_payment_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(payment_date) AS payment_year FROM payments
|
||||
UNION SELECT DISTINCT YEAR(revenue_date) AS payment_year FROM revenues
|
||||
ORDER BY payment_year DESC"
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-users mr-2"></i>Income By Client <small>(With payments of 600 or more)</small></h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<option value="all" <?php if ($year == 'all') { ?> selected <?php } ?> >All Years</option>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_payment_years)) {
|
||||
$payment_year = intval($row['payment_year']);
|
||||
?>
|
||||
<option <?php if ($year == $payment_year) { ?> selected <?php } ?> > <?php echo $payment_year; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
$sql_clients = "SELECT c.client_id, c.client_name, SUM(p.payment_amount) AS amount_paid
|
||||
FROM clients AS c
|
||||
JOIN invoices AS i ON c.client_id = i.invoice_client_id
|
||||
JOIN payments AS p ON i.invoice_id = p.payment_invoice_id";
|
||||
if ($year != 'all') {
|
||||
$sql_clients .= " WHERE YEAR(p.payment_date) = $year";
|
||||
}
|
||||
$sql_clients .= " GROUP BY c.client_id
|
||||
HAVING amount_paid > 599
|
||||
ORDER BY amount_paid DESC";
|
||||
|
||||
$sql_clients = mysqli_query($mysqli, $sql_clients);
|
||||
?>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Paid</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_clients)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$amount_paid = floatval($row['amount_paid']);
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><a href="client_overview.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $amount_paid, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
|
||||
234
reports/income_summary.php
Normal file
234
reports/income_summary.php
Normal file
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_payment_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(payment_date) AS payment_year FROM payments
|
||||
UNION SELECT DISTINCT YEAR(revenue_date) AS payment_year FROM revenues
|
||||
ORDER BY payment_year DESC");
|
||||
|
||||
$sql_categories = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' ORDER BY category_name ASC");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-coins mr-2"></i>Income Summary</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<form class="p-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_payment_years)) {
|
||||
$payment_year = intval($row['payment_year']);
|
||||
?>
|
||||
<option <?php if ($year == $payment_year) { ?> selected <?php } ?> > <?php echo $payment_year; ?></option>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<canvas id="cashFlow" width="100%" height="20"></canvas>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th class="text-right">January</th>
|
||||
<th class="text-right">February</th>
|
||||
<th class="text-right">March</th>
|
||||
<th class="text-right">April</th>
|
||||
<th class="text-right">May</th>
|
||||
<th class="text-right">June</th>
|
||||
<th class="text-right">July</th>
|
||||
<th class="text-right">August</th>
|
||||
<th class="text-right">September</th>
|
||||
<th class="text-right">October</th>
|
||||
<th class="text-right">November</th>
|
||||
<th class="text-right">December</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_categories)) {
|
||||
$category_id = intval($row['category_id']);
|
||||
$category_name = nullable_htmlentities($row['category_name']);
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $category_name; ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$total_payment_for_all_months = 0;
|
||||
|
||||
for($month = 1; $month<=12; $month++) {
|
||||
//Payments to Invoices
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_category_id = $category_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_amount_for_month = floatval($row['payment_amount_for_month']);
|
||||
|
||||
//Revenues
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id = $category_id AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenues_amount_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$payment_amount_for_month = $payment_amount_for_month + $revenues_amount_for_month;
|
||||
$total_payment_for_all_months = $payment_amount_for_month + $total_payment_for_all_months;
|
||||
|
||||
|
||||
?>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_amount_for_month, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right text-bold"><?php echo numfmt_format_currency($currency_format, $total_payment_for_all_months, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<?php
|
||||
|
||||
for($month = 1; $month<=12; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_total_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_total_amount_for_month = floatval($row['payment_total_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id > 0 AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenues_total_amount_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$payment_total_amount_for_month = $payment_total_amount_for_month + $revenues_total_amount_for_month;
|
||||
|
||||
|
||||
$total_payment_for_all_months = $payment_total_amount_for_month + $total_payment_for_all_months;
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_total_amount_for_month, $session_company_currency); ?></th>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $total_payment_for_all_months, $session_company_currency); ?></th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php"; ?>
|
||||
|
||||
<script>
|
||||
// Set new default font family and font color to mimic Bootstrap's default styling
|
||||
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
|
||||
Chart.defaults.global.defaultFontColor = '#292b2c';
|
||||
|
||||
// Area Chart Example
|
||||
var ctx = document.getElementById("cashFlow");
|
||||
var myLineChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||
datasets: [{
|
||||
label: "Income",
|
||||
fill: false,
|
||||
borderColor: "#007bff",
|
||||
pointBackgroundColor: "#007bff",
|
||||
pointBorderColor: "#007bff",
|
||||
pointHoverRadius: 5,
|
||||
pointHoverBackgroundColor: "#007bff",
|
||||
pointHitRadius: 50,
|
||||
pointBorderWidth: 2,
|
||||
data: [
|
||||
<?php
|
||||
|
||||
for ($month = 1; $month<=12; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payments_for_month = floatval($row['payment_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id > 0 AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenues_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$income_for_month = $payments_for_month + $revenues_for_month;
|
||||
|
||||
if ($income_for_month > 0 && $income_for_month > $largest_income_month) {
|
||||
$largest_income_month = $income_for_month;
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
<?php echo "$income_for_month,"; ?>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
time: {
|
||||
unit: 'date'
|
||||
},
|
||||
gridLines: {
|
||||
display: false
|
||||
},
|
||||
ticks: {
|
||||
maxTicksLimit: 12
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 0,
|
||||
max: <?php $max = max(1000, $largest_income_month, $largest_invoice_month); echo roundUpToNearestMultiple($max); ?>,
|
||||
maxTicksLimit: 5
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, .125)",
|
||||
}
|
||||
}],
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
20
reports/index.php
Normal file
20
reports/index.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-coins mr-2"></i>Reports</h3>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<form class="p-3">
|
||||
<h3>Access different reports using the menu on the left</h3>
|
||||
<small class="text-muted">In addition to the general reporting permission, you must have read permissions to the reporting area you wish to view (e.g. support/financial).</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php"; ?>
|
||||
|
||||
437
reports/profit_loss.php
Normal file
437
reports/profit_loss.php
Normal file
@@ -0,0 +1,437 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
//GET unique years from expenses, payments and revenues
|
||||
$sql_all_years = 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
|
||||
ORDER BY all_years DESC"
|
||||
);
|
||||
|
||||
$sql_categories_income = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' ORDER BY category_name ASC");
|
||||
|
||||
$sql_categories_expense = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Expense' ORDER BY category_name ASC");
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-balance-scale mr-2"></i>Profit & Loss</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<form class="p-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_all_years)) {
|
||||
$all_years = intval($row['all_years']);
|
||||
?>
|
||||
<option <?php if ($year == $all_years) { ?> selected <?php } ?> > <?php echo $all_years; ?></option>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</form>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-sm">
|
||||
<thead class="text-dark">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="text-right">Jan-Mar</th>
|
||||
<th class="text-right">Apr-Jun</th>
|
||||
<th class="text-right">Jul-Sep</th>
|
||||
<th class="text-right">Oct-Dec</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><br><br>Income</th>
|
||||
<th colspan="5"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_categories_income)) {
|
||||
$category_id = intval($row['category_id']);
|
||||
$category_name = nullable_htmlentities($row['category_name']);
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $category_name; ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_amount_for_quarter_one = 0;
|
||||
|
||||
for($month = 1; $month<=3; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_category_id = $category_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_amount_for_month = floatval($row['payment_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id = $category_id AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_amount_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$payment_amount_for_month = $payment_amount_for_month + $revenue_amount_for_month;
|
||||
|
||||
$payment_amount_for_quarter_one = $payment_amount_for_quarter_one + $payment_amount_for_month;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_amount_for_quarter_one, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_amount_for_quarter_two = 0;
|
||||
|
||||
for($month = 4; $month<=6; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_category_id = $category_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_amount_for_month = floatval($row['payment_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id = $category_id AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_amount_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$payment_amount_for_month = $payment_amount_for_month + $revenue_amount_for_month;
|
||||
|
||||
$payment_amount_for_quarter_two = $payment_amount_for_quarter_two + $payment_amount_for_month;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_amount_for_quarter_two, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_amount_for_quarter_three = 0;
|
||||
|
||||
for($month = 7; $month<=9; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_category_id = $category_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_amount_for_month = floatval($row['payment_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id = $category_id AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_amount_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$payment_amount_for_month = $payment_amount_for_month + $revenue_amount_for_month;
|
||||
$payment_amount_for_quarter_three = $payment_amount_for_quarter_three + $payment_amount_for_month;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_amount_for_quarter_three, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_amount_for_quarter_four = 0;
|
||||
|
||||
for($month = 10; $month<=12; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_category_id = $category_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_amount_for_month = floatval($row['payment_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_amount_for_month FROM revenues WHERE revenue_category_id = $category_id AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_amount_for_month = floatval($row['revenue_amount_for_month']);
|
||||
|
||||
$payment_amount_for_month = $payment_amount_for_month + $revenue_amount_for_month;
|
||||
$payment_amount_for_quarter_four = $payment_amount_for_quarter_four + $payment_amount_for_month;
|
||||
}
|
||||
|
||||
$total_payments_for_all_four_quarters = $payment_amount_for_quarter_one + $payment_amount_for_quarter_two + $payment_amount_for_quarter_three + $payment_amount_for_quarter_four;
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_amount_for_quarter_four, $session_company_currency); ?></td>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $total_payments_for_all_four_quarters, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
$total_payment_for_all_months = 0;
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<th>Gross Profit</th>
|
||||
<?php
|
||||
|
||||
$payment_total_amount_for_quarter_one = 0;
|
||||
|
||||
for($month = 1; $month<=3; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_total_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_total_amount_for_month = floatval($row['payment_total_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_total_amount_for_month FROM revenues WHERE revenue_category_id > 0 AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_total_amount_for_month = floatval($row['revenue_total_amount_for_month']);
|
||||
|
||||
$payment_total_amount_for_month = $payment_total_amount_for_month + $revenue_total_amount_for_month;
|
||||
|
||||
$payment_total_amount_for_quarter_one = $payment_total_amount_for_quarter_one + $payment_total_amount_for_month;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_total_amount_for_quarter_one, $session_company_currency); ?></th>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_total_amount_for_quarter_two = 0;
|
||||
|
||||
for($month = 4; $month<=6; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_total_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_total_amount_for_month = floatval($row['payment_total_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_total_amount_for_month FROM revenues WHERE revenue_category_id > 0 AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_total_amount_for_month = floatval($row['revenue_total_amount_for_month']);
|
||||
|
||||
$payment_total_amount_for_month = $payment_total_amount_for_month + $revenue_total_amount_for_month;
|
||||
|
||||
$payment_total_amount_for_quarter_two = $payment_total_amount_for_quarter_two + $payment_total_amount_for_month;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_total_amount_for_quarter_two, $session_company_currency); ?></th>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_total_amount_for_quarter_three = 0;
|
||||
|
||||
for($month = 7; $month<=9; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_total_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_total_amount_for_month = floatval($row['payment_total_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_total_amount_for_month FROM revenues WHERE revenue_category_id > 0 AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_total_amount_for_month = floatval($row['revenue_total_amount_for_month']);
|
||||
|
||||
$payment_total_amount_for_month = $payment_total_amount_for_month + $revenue_total_amount_for_month;
|
||||
|
||||
$payment_total_amount_for_quarter_three = $payment_total_amount_for_quarter_three + $payment_total_amount_for_month;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_total_amount_for_quarter_three, $session_company_currency); ?></th>
|
||||
|
||||
<?php
|
||||
|
||||
$payment_total_amount_for_quarter_four = 0;
|
||||
|
||||
for($month = 10; $month<=12; $month++) {
|
||||
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS payment_total_amount_for_month FROM payments, invoices WHERE payment_invoice_id = invoice_id AND YEAR(payment_date) = $year AND MONTH(payment_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_payments);
|
||||
$payment_total_amount_for_month = floatval($row['payment_total_amount_for_month']);
|
||||
|
||||
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS revenue_total_amount_for_month FROM revenues WHERE revenue_category_id > 0 AND YEAR(revenue_date) = $year AND MONTH(revenue_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_revenues);
|
||||
$revenue_total_amount_for_month = floatval($row['revenue_total_amount_for_month']);
|
||||
|
||||
$payment_total_amount_for_month = $payment_total_amount_for_month + $revenue_total_amount_for_month;
|
||||
|
||||
$payment_total_amount_for_quarter_four = $payment_total_amount_for_quarter_four + $payment_total_amount_for_month;
|
||||
}
|
||||
|
||||
$total_payments_for_all_four_quarters = $payment_total_amount_for_quarter_one + $payment_total_amount_for_quarter_two + $payment_total_amount_for_quarter_three + $payment_total_amount_for_quarter_four;
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $payment_total_amount_for_quarter_four, $session_company_currency); ?></th>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $total_payments_for_all_four_quarters, $session_company_currency); ?></th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th><br><br>Expenses</th>
|
||||
<th colspan="5"></th>
|
||||
</tr>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_categories_expense)) {
|
||||
$category_id = intval($row['category_id']);
|
||||
$category_name = nullable_htmlentities($row['category_name']);
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $category_name; ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_amount_for_quarter_one = 0;
|
||||
|
||||
for($month = 1; $month<=3; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_amount_for_month FROM expenses WHERE expense_category_id = $category_id AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_amount_for_quarter_one = $expense_amount_for_quarter_one + floatval($row['expense_amount_for_month']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_amount_for_quarter_one, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_amount_for_quarter_two = 0;
|
||||
|
||||
for($month = 4; $month<=6; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_amount_for_month FROM expenses WHERE expense_category_id = $category_id AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_amount_for_quarter_two = $expense_amount_for_quarter_two + floatval($row['expense_amount_for_month']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_amount_for_quarter_two, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_amount_for_quarter_three = 0;
|
||||
|
||||
for($month = 7; $month<=9; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_amount_for_month FROM expenses WHERE expense_category_id = $category_id AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_amount_for_quarter_three = $expense_amount_for_quarter_three + floatval($row['expense_amount_for_month']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_amount_for_quarter_three, $session_company_currency); ?></td>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_amount_for_quarter_four = 0;
|
||||
|
||||
for($month = 10; $month<=12; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_amount_for_month FROM expenses WHERE expense_category_id = $category_id AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_amount_for_quarter_four = $expense_amount_for_quarter_four + floatval($row['expense_amount_for_month']);
|
||||
}
|
||||
|
||||
$total_expenses_for_all_four_quarters = $expense_amount_for_quarter_one + $expense_amount_for_quarter_two + $expense_amount_for_quarter_three + $expense_amount_for_quarter_four;
|
||||
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_amount_for_quarter_four, $session_company_currency); ?></td>
|
||||
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $total_expenses_for_all_four_quarters, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
$total_expense_for_all_months = 0;
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<th>Total Expenses<br><br><br></th>
|
||||
<?php
|
||||
|
||||
$expense_total_amount_for_quarter_one = 0;
|
||||
|
||||
for($month = 1; $month<=3; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_total_amount_for_month FROM expenses WHERE expense_category_id > 0 AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month AND expense_vendor_id > 0");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_total_amount_for_quarter_one = $expense_total_amount_for_quarter_one + floatval($row['expense_total_amount_for_month']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_total_amount_for_quarter_one, $session_company_currency); ?></th>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_total_amount_for_quarter_two = 0;
|
||||
|
||||
for($month = 4; $month<=6; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_total_amount_for_month FROM expenses WHERE expense_category_id > 0 AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month AND expense_vendor_id > 0");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_total_amount_for_quarter_two = $expense_total_amount_for_quarter_two + floatval($row['expense_total_amount_for_month']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_total_amount_for_quarter_two, $session_company_currency); ?></th>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_total_amount_for_quarter_three = 0;
|
||||
|
||||
for($month = 7; $month<=9; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_total_amount_for_month FROM expenses WHERE expense_category_id > 0 AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month AND expense_vendor_id > 0");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_total_amount_for_quarter_three = $expense_total_amount_for_quarter_three + floatval($row['expense_total_amount_for_month']);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_total_amount_for_quarter_three, $session_company_currency); ?></th>
|
||||
|
||||
<?php
|
||||
|
||||
$expense_total_amount_for_quarter_four = 0;
|
||||
|
||||
for($month = 10; $month<=12; $month++) {
|
||||
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS expense_total_amount_for_month FROM expenses WHERE expense_category_id > 0 AND YEAR(expense_date) = $year AND MONTH(expense_date) = $month AND expense_vendor_id > 0");
|
||||
$row = mysqli_fetch_array($sql_expenses);
|
||||
$expense_total_amount_for_quarter_four = $expense_total_amount_for_quarter_four + floatval($row['expense_total_amount_for_month']);
|
||||
}
|
||||
|
||||
$total_expenses_for_all_four_quarters = $expense_total_amount_for_quarter_one + $expense_total_amount_for_quarter_two + $expense_total_amount_for_quarter_three + $expense_total_amount_for_quarter_four;
|
||||
|
||||
?>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $expense_total_amount_for_quarter_four, $session_company_currency); ?></th>
|
||||
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $total_expenses_for_all_four_quarters, $session_company_currency); ?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<?php
|
||||
$net_profit_quarter_one = $payment_total_amount_for_quarter_one - $expense_total_amount_for_quarter_one;
|
||||
$net_profit_quarter_two = $payment_total_amount_for_quarter_two - $expense_total_amount_for_quarter_two;
|
||||
$net_profit_quarter_three = $payment_total_amount_for_quarter_three - $expense_total_amount_for_quarter_three;
|
||||
$net_profit_quarter_four = $payment_total_amount_for_quarter_four - $expense_total_amount_for_quarter_four;
|
||||
$net_profit_year = $total_payments_for_all_four_quarters - $total_expenses_for_all_four_quarters;
|
||||
?>
|
||||
|
||||
<th>Net Profit</th>
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $net_profit_quarter_one, $session_company_currency); ?></th>
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $net_profit_quarter_two, $session_company_currency); ?></th>
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $net_profit_quarter_three, $session_company_currency); ?></th>
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $net_profit_quarter_four, $session_company_currency); ?></th>
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $net_profit_year, $session_company_currency); ?></th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
|
||||
67
reports/recurring_by_client.php
Normal file
67
reports/recurring_by_client.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
validateAccountantRole();
|
||||
|
||||
$sql = mysqli_query($mysqli, "
|
||||
SELECT client_id, client_name,
|
||||
SUM(CASE WHEN recurring_invoice_frequency = 'month' THEN recurring_invoice_amount
|
||||
WHEN recurring_invoice_frequency = 'year' THEN recurring_invoice_amount / 12 END) AS recurring_monthly_total
|
||||
FROM clients
|
||||
LEFT JOIN recurring_invoices ON client_id = recurring_invoice_client_id
|
||||
WHERE recurring_invoice_status = 1
|
||||
GROUP BY clients.client_id
|
||||
HAVING recurring_monthly_total > 0
|
||||
ORDER BY recurring_monthly_total DESC
|
||||
");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-sync mr-2"></i>Recurring Income By Client</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Monthly Recurring</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$recurring_monthly_total = floatval($row['recurring_monthly_total']);
|
||||
$recurring_total = $recurring_total + $recurring_monthly_total;
|
||||
?>
|
||||
|
||||
|
||||
<tr>
|
||||
<td><a href="client_overview.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $recurring_monthly_total, $session_company_currency); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th>Total Monthly Income</th>
|
||||
<th class="text-right"><?php echo numfmt_format_currency($currency_format, $recurring_total, $session_company_currency); ?></th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
?>
|
||||
121
reports/tax_summary.php
Normal file
121
reports/tax_summary.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_financial');
|
||||
|
||||
$year = isset($_GET['year']) ? intval($_GET['year']) : date('Y');
|
||||
|
||||
$view = isset($_GET['view']) ? $_GET['view'] : 'quarterly';
|
||||
|
||||
$currency_row = mysqli_fetch_array(mysqli_query($mysqli,"SELECT company_currency FROM companies WHERE company_id = 1"));
|
||||
$company_currency = nullable_htmlentities($currency_row['company_currency']);
|
||||
|
||||
// GET unique years from expenses, payments and revenues
|
||||
$sql_all_years = mysqli_query($mysqli, "SELECT DISTINCT(YEAR(item_created_at)) AS all_years FROM invoice_items ORDER BY all_years DESC");
|
||||
|
||||
$sql_tax = mysqli_query($mysqli, "SELECT `tax_name` FROM `taxes`");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-balance-scale mr-2"></i>Collected Tax Summary</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<form class="p-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_all_years)) {
|
||||
$all_years = intval($row['all_years']);
|
||||
?>
|
||||
<option <?php if ($year == $all_years) { echo "selected"; } ?> > <?php echo $all_years; ?></option>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
|
||||
<!-- View Selection Dropdown -->
|
||||
<select onchange="this.form.submit()" class="form-control" name="view">
|
||||
<option value="monthly" <?php if ($view == 'monthly') echo "selected"; ?>>Monthly</option>
|
||||
<option value="quarterly" <?php if ($view == 'quarterly') echo "selected"; ?>>Quarterly</option>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-sm">
|
||||
<thead class="text-dark">
|
||||
<tr>
|
||||
<th>Tax</th>
|
||||
<?php
|
||||
if ($view == 'monthly') {
|
||||
for ($i = 1; $i <= 12; $i++) {
|
||||
echo "<th class='text-right'>" . date('M', mktime(0, 0, 0, $i, 10)) . "</th>";
|
||||
}
|
||||
} else {
|
||||
echo "<th class='text-right'>Jan-Mar</th>";
|
||||
echo "<th class='text-right'>Apr-Jun</th>";
|
||||
echo "<th class='text-right'>Jul-Sep</th>";
|
||||
echo "<th class='text-right'>Oct-Dec</th>";
|
||||
}
|
||||
?>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_tax)) {
|
||||
$tax_name = sanitizeInput($row['tax_name']);
|
||||
echo "<tr>";
|
||||
echo "<td>" . $row['tax_name'] . "</td>";
|
||||
|
||||
if ($view == 'monthly') {
|
||||
for ($i = 1; $i <= 12; $i++) {
|
||||
$monthly_tax = getMonthlyTax($tax_name, $i, $year, $mysqli);
|
||||
echo "<td class='text-right'>" . numfmt_format_currency($currency_format, $monthly_tax, $company_currency) . "</td>";
|
||||
}
|
||||
} else {
|
||||
for ($q = 1; $q <= 4; $q++) {
|
||||
$quarterly_tax = getQuarterlyTax($tax_name, $q, $year, $mysqli);
|
||||
echo "<td class='text-right'>" . numfmt_format_currency($currency_format, $quarterly_tax, $company_currency) . "</td>";
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate total for row and echo bold
|
||||
$total_tax = getTotalTax($tax_name, $year, $mysqli);
|
||||
echo "<td class='text-right text-bold'>" . numfmt_format_currency($currency_format, $total_tax, $company_currency) . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<th>Total</th>
|
||||
<?php
|
||||
if ($view == 'monthly') {
|
||||
for ($i = 1; $i <= 12; $i++) {
|
||||
$monthly_tax = getMonthlyTax($tax_name, $i, $year, $mysqli);
|
||||
echo "<th class='text-right'>" . numfmt_format_currency($currency_format, $monthly_tax, $company_currency) . "</th>";
|
||||
}
|
||||
} else {
|
||||
for ($q = 1; $q <= 4; $q++) {
|
||||
$quarterly_tax = getQuarterlyTax($tax_name, $q, $year, $mysqli);
|
||||
echo "<th class='text-right'>" . numfmt_format_currency($currency_format, $quarterly_tax, $company_currency) . "</th>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
<td class="text-right"></td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
|
||||
300
reports/ticket_by_client.php
Normal file
300
reports/ticket_by_client.php
Normal file
@@ -0,0 +1,300 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_support');
|
||||
|
||||
function secondsToTime($inputSeconds) {
|
||||
$inputSeconds = floor($inputSeconds);
|
||||
|
||||
$secondsInAMinute = 60;
|
||||
$secondsInAnHour = 60 * $secondsInAMinute;
|
||||
$secondsInADay = 24 * $secondsInAnHour;
|
||||
|
||||
// Extract days
|
||||
$days = floor($inputSeconds / $secondsInADay);
|
||||
|
||||
// Extract hours
|
||||
$hourSeconds = $inputSeconds % $secondsInADay;
|
||||
$hours = floor($hourSeconds / $secondsInAnHour);
|
||||
|
||||
// Extract minutes
|
||||
$minuteSeconds = $hourSeconds % $secondsInAnHour;
|
||||
$minutes = floor($minuteSeconds / $secondsInAMinute);
|
||||
|
||||
// Extract the remaining seconds
|
||||
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
|
||||
$seconds = ceil($remainingSeconds);
|
||||
|
||||
// Format and return
|
||||
$timeParts = [];
|
||||
$sections = [
|
||||
'day' => (int)$days,
|
||||
'hour' => (int)$hours,
|
||||
'minute' => (int)$minutes,
|
||||
'second' => (int)$seconds,
|
||||
];
|
||||
|
||||
foreach ($sections as $name => $value){
|
||||
if ($value > 0){
|
||||
$timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's');
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $timeParts);
|
||||
}
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
if (isset($_GET['month'])) {
|
||||
$month = intval($_GET['month']);
|
||||
} else {
|
||||
$month = date('m');
|
||||
}
|
||||
|
||||
$sql_ticket_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(ticket_created_at) AS ticket_year FROM tickets ORDER BY ticket_year DESC");
|
||||
|
||||
$sql_clients = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Tickets By Client</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_ticket_years)) {
|
||||
$ticket_year = intval($row['ticket_year']); ?>
|
||||
<option <?php if ($year == $ticket_year) { ?> selected <?php } ?> > <?php echo $ticket_year; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<select onchange="this.form.submit()" class="form-control" name="month">
|
||||
<option <?php if ($month == 1) { echo 'selected'; } ?> value="1">January</option>
|
||||
<option <?php if ($month == 2) { echo 'selected'; } ?> value="2">February</option>
|
||||
<option <?php if ($month == 3) { echo 'selected'; } ?> value="3">March</option>
|
||||
<option <?php if ($month == 4) { echo 'selected'; } ?> value="4">April</option>
|
||||
<option <?php if ($month == 5) { echo 'selected'; } ?> value="5">May</option>
|
||||
<option <?php if ($month == 6) { echo 'selected'; } ?> value="6">June</option>
|
||||
<option <?php if ($month == 7) { echo 'selected'; } ?> value="7">July</option>
|
||||
<option <?php if ($month == 8) { echo 'selected'; } ?> value="8">August</option>
|
||||
<option <?php if ($month == 9) { echo 'selected'; } ?> value="9">September</option>
|
||||
<option <?php if ($month == 10) { echo 'selected'; } ?> value="10">October</option>
|
||||
<option <?php if ($month == 11) { echo 'selected'; } ?> value="11">November</option>
|
||||
<option <?php if ($month == 12) { echo 'selected'; } ?> value="12">December</option>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<div class="card card-dark mb-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-chart-area mr-2"></i>Yearly (<?php echo $year; ?>)</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Tickets raised</th>
|
||||
<th class="text-right">By priority: Low</th>
|
||||
<th class="text-right">By priority: Med</th>
|
||||
<th class="text-right">By priority: High</th>
|
||||
<th class="text-right">Tickets resolved</th>
|
||||
<th class="text-right">Total Time worked <i>(H:M:S)</i></th>
|
||||
<th class="text-right">Avg time to resolve</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_clients)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
|
||||
// Calculate total tickets raised in period
|
||||
$sql_ticket_raised_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS ticket_raised_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id");
|
||||
$row = mysqli_fetch_array($sql_ticket_raised_count);
|
||||
$ticket_raised_count = intval($row['ticket_raised_count']);
|
||||
|
||||
// Calculate total tickets raised in period that are resolved
|
||||
$sql_ticket_resolved_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS ticket_resolved_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id AND ticket_resolved_at IS NOT NULL");
|
||||
$row = mysqli_fetch_array($sql_ticket_resolved_count);
|
||||
$ticket_resolved_count = intval($row['ticket_resolved_count']);
|
||||
|
||||
// Breakdown tickets for each priority - Low
|
||||
$sql_low_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS low_ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id AND ticket_priority = 'Low'");
|
||||
$row = mysqli_fetch_array($sql_low_ticket_count);
|
||||
$low_ticket_count = intval($row['low_ticket_count']);
|
||||
|
||||
// Breakdown tickets for each priority - Low
|
||||
$sql_med_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS med_ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id AND ticket_priority = 'Medium'");
|
||||
$row = mysqli_fetch_array($sql_med_ticket_count);
|
||||
$med_ticket_count = intval($row['med_ticket_count']);
|
||||
|
||||
// Breakdown tickets for each priority - Low
|
||||
$sql_high_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS high_ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id AND ticket_priority = 'High'");
|
||||
$row = mysqli_fetch_array($sql_high_ticket_count);
|
||||
$high_ticket_count = intval($row['high_ticket_count']);
|
||||
|
||||
// Used to calculate average time to resolve tickets that were raised in period specified
|
||||
$sql_tickets = mysqli_query($mysqli, "SELECT ticket_created_at, ticket_resolved_at FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id AND ticket_resolved_at IS NOT NULL");
|
||||
|
||||
// Calculate total time tracked towards tickets in the period
|
||||
$sql_time = mysqli_query($mysqli, "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(ticket_reply_time_worked))) as total_time FROM ticket_replies LEFT JOIN tickets ON tickets.ticket_id = ticket_replies.ticket_reply_ticket_id WHERE YEAR(ticket_created_at) = $year AND ticket_client_id = $client_id AND ticket_reply_time_worked IS NOT NULL");
|
||||
$row = mysqli_fetch_array($sql_time);
|
||||
$ticket_total_time_worked = nullable_htmlentities($row['total_time']);
|
||||
|
||||
if ($ticket_raised_count > 0 || $ticket_resolved_count > 0) {
|
||||
|
||||
$avg_time_to_resolve = '-';
|
||||
if ($ticket_resolved_count > 0) {
|
||||
// Calculate average time to solve
|
||||
$count = 0;
|
||||
$total = 0;
|
||||
while ($row = mysqli_fetch_array($sql_tickets)) {
|
||||
$openedTime = new DateTime($row['ticket_created_at']);
|
||||
$resolvedTime = new DateTime($row['ticket_resolved_at']);
|
||||
|
||||
$total += ($resolvedTime->getTimestamp() - $openedTime->getTimestamp());
|
||||
$count++;
|
||||
}
|
||||
$avg_time_to_resolve = secondsToTime($total / $count);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $client_name; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_raised_count; ?></td>
|
||||
<td class="text-right"><?php echo $low_ticket_count; ?></td>
|
||||
<td class="text-right"><?php echo $med_ticket_count; ?></td>
|
||||
<td class="text-right"><?php echo $high_ticket_count; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_resolved_count; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_total_time_worked; ?></td>
|
||||
<td class="text-right"><?php echo $avg_time_to_resolve; ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="card card-dark mb-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-chart-area mr-2"></i>Monthly (<?php echo date("F", mktime(1, 1, 1, $month, 1)) . ' ' . $year; ?>)</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Tickets raised</th>
|
||||
<th class="text-right">By priority: Low</th>
|
||||
<th class="text-right">By priority: Med</th>
|
||||
<th class="text-right">By priority: High</th>
|
||||
<th class="text-right">Tickets resolved</th>
|
||||
<th class="text-right">Total Time worked <i>(H:M:S)</i></th>
|
||||
<th class="text-right">Avg time to resolve</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
mysqli_data_seek($sql_clients, 0); // Reset
|
||||
while ($row = mysqli_fetch_array($sql_clients)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
|
||||
// Calculate total tickets raised in period
|
||||
$sql_ticket_raised_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS ticket_raised_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id");
|
||||
$row = mysqli_fetch_array($sql_ticket_raised_count);
|
||||
$ticket_raised_count = intval($row['ticket_raised_count']);
|
||||
|
||||
// Calculate total tickets raised in period that are resolved
|
||||
$sql_ticket_resolved_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS ticket_resolved_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id AND ticket_resolved_at IS NOT NULL");
|
||||
$row = mysqli_fetch_array($sql_ticket_resolved_count);
|
||||
$ticket_resolved_count = intval($row['ticket_resolved_count']);
|
||||
|
||||
// Breakdown tickets for each priority - Low
|
||||
$sql_low_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS low_ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id AND ticket_priority = 'Low'");
|
||||
$row = mysqli_fetch_array($sql_low_ticket_count);
|
||||
$low_ticket_count = intval($row['low_ticket_count']);
|
||||
|
||||
// Breakdown tickets for each priority - Low
|
||||
$sql_med_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS med_ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id AND ticket_priority = 'Medium'");
|
||||
$row = mysqli_fetch_array($sql_med_ticket_count);
|
||||
$med_ticket_count = intval($row['med_ticket_count']);
|
||||
|
||||
// Breakdown tickets for each priority - Low
|
||||
$sql_high_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS high_ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id AND ticket_priority = 'High'");
|
||||
$row = mysqli_fetch_array($sql_high_ticket_count);
|
||||
$high_ticket_count = intval($row['high_ticket_count']);
|
||||
|
||||
// Used to calculate average time to resolve tickets that were raised in period specified
|
||||
$sql_tickets = mysqli_query($mysqli, "SELECT ticket_created_at, ticket_resolved_at FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id AND ticket_resolved_at IS NOT NULL");
|
||||
|
||||
// Calculate total time tracked towards tickets in the period
|
||||
$sql_time = mysqli_query($mysqli, "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(ticket_reply_time_worked))) as total_time FROM ticket_replies LEFT JOIN tickets ON tickets.ticket_id = ticket_replies.ticket_reply_ticket_id WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month AND ticket_client_id = $client_id AND ticket_reply_time_worked IS NOT NULL");
|
||||
$row = mysqli_fetch_array($sql_time);
|
||||
$ticket_total_time_worked = nullable_htmlentities($row['total_time']);
|
||||
|
||||
if ($ticket_raised_count > 0 || $ticket_resolved_count > 0) {
|
||||
|
||||
$avg_time_to_resolve = '-';
|
||||
if ($ticket_resolved_count > 0) {
|
||||
// Calculate average time to solve
|
||||
$count = 0;
|
||||
$total = 0;
|
||||
while ($row = mysqli_fetch_array($sql_tickets)) {
|
||||
$openedTime = new DateTime($row['ticket_created_at']);
|
||||
$resolvedTime = new DateTime($row['ticket_resolved_at']);
|
||||
|
||||
$total += ($resolvedTime->getTimestamp() - $openedTime->getTimestamp());
|
||||
$count++;
|
||||
}
|
||||
$avg_time_to_resolve = secondsToTime($total / $count);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $client_name; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_raised_count; ?></td>
|
||||
<td class="text-right"><?php echo $low_ticket_count; ?></td>
|
||||
<td class="text-right"><?php echo $med_ticket_count; ?></td>
|
||||
<td class="text-right"><?php echo $high_ticket_count; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_resolved_count; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_total_time_worked; ?></td>
|
||||
<td class="text-right"><?php echo $avg_time_to_resolve; ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
|
||||
161
reports/ticket_summary.php
Normal file
161
reports/ticket_summary.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_support');
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_ticket_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(ticket_created_at) AS ticket_year FROM tickets ORDER BY ticket_year DESC");
|
||||
|
||||
$sql_tickets = mysqli_query($mysqli, "SELECT ticket_id FROM tickets");
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Ticket Summary</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<form class="p-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_ticket_years)) {
|
||||
$ticket_year = intval($row['ticket_year']); ?>
|
||||
<option <?php if ($year == $ticket_year) { ?> selected <?php } ?> > <?php echo $ticket_year; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<canvas id="tickets" width="100%" height="20"></canvas>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-right">January</th>
|
||||
<th class="text-right">February</th>
|
||||
<th class="text-right">March</th>
|
||||
<th class="text-right">April</th>
|
||||
<th class="text-right">May</th>
|
||||
<th class="text-right">June</th>
|
||||
<th class="text-right">July</th>
|
||||
<th class="text-right">August</th>
|
||||
<th class="text-right">September</th>
|
||||
<th class="text-right">October</th>
|
||||
<th class="text-right">November</th>
|
||||
<th class="text-right">December</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
|
||||
$total_tickets_for_all_months = 0;
|
||||
|
||||
for ($month = 1; $month<=12; $month++) {
|
||||
|
||||
$sql_tickets = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS tickets_for_month FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month");
|
||||
$row = mysqli_fetch_array($sql_tickets);
|
||||
$tickets_for_month = intval($row['tickets_for_month']);
|
||||
|
||||
$total_tickets_for_all_months = $tickets_for_month + $total_tickets_for_all_months;
|
||||
?>
|
||||
|
||||
<td class="text-right"><?php echo $tickets_for_month; ?></td>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
|
||||
<td class="text-right"><b><?php echo $total_tickets_for_all_months; ?></b></td>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
?>
|
||||
|
||||
<script>
|
||||
// Set new default font family and font color to mimic Bootstrap's default styling
|
||||
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
|
||||
Chart.defaults.global.defaultFontColor = '#292b2c';
|
||||
|
||||
// Area Chart Example
|
||||
var ctx = document.getElementById("tickets");
|
||||
var myLineChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||
datasets: [{
|
||||
label: "Tickets Raised",
|
||||
fill: false,
|
||||
borderColor: "#007bff",
|
||||
pointBackgroundColor: "#007bff",
|
||||
pointBorderColor: "#007bff",
|
||||
pointHoverRadius: 5,
|
||||
pointHoverBackgroundColor: "#007bff",
|
||||
pointHitRadius: 50,
|
||||
pointBorderWidth: 2,
|
||||
data: [
|
||||
<?php
|
||||
|
||||
$largest_ticket_month = 0;
|
||||
|
||||
for ($month = 1; $month<=12; $month++) {
|
||||
|
||||
$sql_tickets = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS tickets_for_month FROM tickets WHERE YEAR(ticket_created_at) = $year AND MONTH(ticket_created_at) = $month");
|
||||
$row = mysqli_fetch_array($sql_tickets);
|
||||
$tickets_for_month = intval($row['tickets_for_month']);
|
||||
|
||||
if ($tickets_for_month > 0 && $tickets_for_month > $largest_ticket_month) {
|
||||
$largest_ticket_month = $tickets_for_month;
|
||||
}
|
||||
|
||||
echo "$tickets_for_month,";
|
||||
}
|
||||
?>
|
||||
|
||||
],
|
||||
}],
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
xAxes: [{
|
||||
time: {
|
||||
unit: 'date'
|
||||
},
|
||||
gridLines: {
|
||||
display: false
|
||||
},
|
||||
ticks: {
|
||||
maxTicksLimit: 12
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
min: 0,
|
||||
max: <?php echo $largest_ticket_month ?>,
|
||||
maxTicksLimit: 5
|
||||
},
|
||||
gridLines: {
|
||||
color: "rgba(0, 0, 0, .125)",
|
||||
}
|
||||
}],
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
182
reports/tickets_unbilled.php
Normal file
182
reports/tickets_unbilled.php
Normal file
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_sales', 1);
|
||||
|
||||
function secondsToTime($inputSeconds) {
|
||||
$secondsInAMinute = 60;
|
||||
$secondsInAnHour = 60 * $secondsInAMinute;
|
||||
$secondsInADay = 24 * $secondsInAnHour;
|
||||
|
||||
// Extract days
|
||||
$days = floor($inputSeconds / $secondsInADay);
|
||||
|
||||
// Extract hours
|
||||
$hourSeconds = $inputSeconds % $secondsInADay;
|
||||
$hours = floor($hourSeconds / $secondsInAnHour);
|
||||
|
||||
// Extract minutes
|
||||
$minuteSeconds = $hourSeconds % $secondsInAnHour;
|
||||
$minutes = floor($minuteSeconds / $secondsInAMinute);
|
||||
|
||||
// Extract the remaining seconds
|
||||
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
|
||||
$seconds = ceil($remainingSeconds);
|
||||
|
||||
// Format and return
|
||||
$timeParts = [];
|
||||
$sections = [
|
||||
'day' => (int)$days,
|
||||
'hour' => (int)$hours,
|
||||
'minute' => (int)$minutes,
|
||||
'second' => (int)$seconds,
|
||||
];
|
||||
|
||||
foreach ($sections as $name => $value){
|
||||
if ($value > 0){
|
||||
$timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's');
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $timeParts);
|
||||
}
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
$sql_ticket_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(ticket_created_at) AS ticket_year FROM tickets ORDER BY ticket_year DESC");
|
||||
|
||||
$sql_clients = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients ORDER BY client_name ASC");
|
||||
|
||||
$rows = 0;
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Unbilled Tickets By Client</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_ticket_years)) {
|
||||
$ticket_year = intval($row['ticket_year']); ?>
|
||||
<option <?php if ($year == $ticket_year) { ?> selected <?php } ?> > <?php echo $ticket_year; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th class="text-right">Tickets Raised</th>
|
||||
<th class="text-right">Billable Tickets</th>
|
||||
<th class="text-right">Unbilled Tickets</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_clients)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
|
||||
// Calculate total tickets raised in period
|
||||
$sql_ticket_raised_count = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT
|
||||
COUNT(ticket_id) AS ticket_raised_count
|
||||
FROM
|
||||
tickets
|
||||
WHERE
|
||||
YEAR(ticket_created_at) = $year
|
||||
AND
|
||||
ticket_client_id = $client_id"
|
||||
);
|
||||
$row = mysqli_fetch_array($sql_ticket_raised_count);
|
||||
$ticket_raised_count = intval($row['ticket_raised_count']);
|
||||
|
||||
// Calculate total tickets raised in period that are closed and billable
|
||||
$sql_ticket_closed_count = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT
|
||||
COUNT(ticket_id) AS ticket_closed_count
|
||||
FROM
|
||||
tickets
|
||||
WHERE
|
||||
YEAR(ticket_created_at) = $year
|
||||
AND
|
||||
ticket_client_id = $client_id
|
||||
AND
|
||||
ticket_closed_at IS NOT NULL
|
||||
AND
|
||||
ticket_billable = 1
|
||||
");
|
||||
$row = mysqli_fetch_array($sql_ticket_closed_count);
|
||||
$ticket_closed_count = intval($row['ticket_closed_count']);
|
||||
|
||||
// Calculate total tickets raised in period that are closed and billable, but not invoiced
|
||||
$sql_ticket_unbilled_count = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT
|
||||
COUNT(ticket_id) AS ticket_unbilled_count
|
||||
FROM
|
||||
tickets
|
||||
WHERE
|
||||
YEAR(ticket_created_at) = $year
|
||||
AND
|
||||
ticket_client_id = $client_id
|
||||
AND
|
||||
ticket_closed_at IS NOT NULL
|
||||
AND
|
||||
ticket_billable = 1
|
||||
AND
|
||||
ticket_invoice_id = 0");
|
||||
$row = mysqli_fetch_array($sql_ticket_unbilled_count);
|
||||
$ticket_unbilled_count = intval($row['ticket_unbilled_count']);
|
||||
|
||||
if ($ticket_unbilled_count > 0) {
|
||||
$rows = $rows + 1;
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<a href="tickets.php?client_id=<?php echo $client_id; ?>&billable=1&unbilled"><?php echo $client_name; ?></a>
|
||||
</td>
|
||||
<td class="text-right"><?php echo $ticket_raised_count; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_closed_count; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_unbilled_count; ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
if ($rows == 0) {
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="4">You are all caught up! There are no unbilled tickets for this year.
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
|
||||
181
reports/time_by_tech.php
Normal file
181
reports/time_by_tech.php
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
require_once "includes/inc_all_reports.php";
|
||||
|
||||
enforceUserPermission('module_support');
|
||||
|
||||
function secondsToTime($inputSeconds) {
|
||||
$inputSeconds = floor($inputSeconds);
|
||||
|
||||
$secondsInAMinute = 60;
|
||||
$secondsInAnHour = 60 * $secondsInAMinute;
|
||||
$secondsInADay = 24 * $secondsInAnHour;
|
||||
|
||||
// Extract days
|
||||
$days = floor($inputSeconds / $secondsInADay);
|
||||
|
||||
// Extract hours
|
||||
$hourSeconds = $inputSeconds % $secondsInADay;
|
||||
$hours = floor($hourSeconds / $secondsInAnHour);
|
||||
|
||||
// Extract minutes
|
||||
$minuteSeconds = $hourSeconds % $secondsInAnHour;
|
||||
$minutes = floor($minuteSeconds / $secondsInAMinute);
|
||||
|
||||
// Extract the remaining seconds
|
||||
$remainingSeconds = $minuteSeconds % $secondsInAMinute;
|
||||
$seconds = ceil($remainingSeconds);
|
||||
|
||||
// Format and return
|
||||
$timeParts = [];
|
||||
$sections = [
|
||||
'day' => (int)$days,
|
||||
'hour' => (int)$hours,
|
||||
'minute' => (int)$minutes,
|
||||
'second' => (int)$seconds,
|
||||
];
|
||||
|
||||
foreach ($sections as $name => $value){
|
||||
if ($value > 0){
|
||||
$timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's');
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $timeParts);
|
||||
}
|
||||
|
||||
if (isset($_GET['year'])) {
|
||||
$year = intval($_GET['year']);
|
||||
} else {
|
||||
$year = date('Y');
|
||||
}
|
||||
|
||||
if (isset($_GET['month'])) {
|
||||
$month = intval($_GET['month']);
|
||||
} else {
|
||||
$month = date('m');
|
||||
}
|
||||
|
||||
$sql_ticket_years = mysqli_query($mysqli, "SELECT DISTINCT YEAR(ticket_created_at) AS ticket_year FROM tickets ORDER BY ticket_year DESC");
|
||||
|
||||
$sql_clients = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
|
||||
$sql_users = mysqli_query($mysqli, "
|
||||
SELECT users.user_id, user_name FROM users
|
||||
LEFT JOIN user_settings on users.user_id = user_settings.user_id
|
||||
WHERE user_type = 1
|
||||
AND user_status = 1
|
||||
AND user_archived_at IS NULL
|
||||
ORDER BY user_name DESC"
|
||||
);
|
||||
// TODO: Maybe try and filter this to just users with the support module perm
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Time Logged By Technician</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary d-print-none" onclick="window.print();"><i class="fas fa-fw fa-print mr-2"></i>Print</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-3">
|
||||
<select onchange="this.form.submit()" class="form-control" name="year">
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql_ticket_years)) {
|
||||
$ticket_year = intval($row['ticket_year']); ?>
|
||||
<option <?php if ($year == $ticket_year) { ?> selected <?php } ?> > <?php echo $ticket_year; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<div class="card card-dark mb-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-chart-area mr-2"></i>Yearly (<?php echo $year; ?>)</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Technician</th>
|
||||
<th class="text-right">Tickets assigned</th>
|
||||
<th class="text-right">Tickets touched</th>
|
||||
<th class="text-right">Total time worked <i>(H:M:S)</i></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($agent_row = mysqli_fetch_array($sql_users)) {
|
||||
$user_id = intval($agent_row['user_id']);
|
||||
$user_name = nullable_htmlentities($agent_row['user_name']);
|
||||
|
||||
// Get tickets in period that are still assigned to the technician/agent
|
||||
$sql_ticket_count = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS ticket_count FROM tickets WHERE YEAR(ticket_created_at) = $year AND ticket_assigned_to = $user_id");
|
||||
$row = mysqli_fetch_array($sql_ticket_count);
|
||||
$ticket_raised_count = intval($row['ticket_count']);
|
||||
|
||||
// Get unique tickets in period that the agent replied to/touched
|
||||
$sql_tickets_touched = mysqli_query($mysqli, "
|
||||
SELECT COUNT(DISTINCT ticket_id) AS tickets_touched
|
||||
FROM (
|
||||
-- Tickets the agent replied to
|
||||
SELECT ticket_reply_ticket_id AS ticket_id
|
||||
FROM ticket_replies
|
||||
WHERE YEAR(ticket_reply_created_at) = $year AND ticket_reply_by = $user_id
|
||||
|
||||
UNION
|
||||
|
||||
-- Tickets the agent opened
|
||||
SELECT ticket_id
|
||||
FROM tickets
|
||||
WHERE YEAR(ticket_created_at) = $year AND ticket_created_by = $user_id
|
||||
|
||||
UNION
|
||||
|
||||
-- Tickets the agent closed
|
||||
SELECT ticket_id
|
||||
FROM tickets
|
||||
WHERE YEAR(ticket_created_at) = $year AND ticket_closed_by = $user_id
|
||||
)
|
||||
AS tickets_touched
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql_tickets_touched);
|
||||
$tickets_touched = intval($row['tickets_touched']);
|
||||
|
||||
|
||||
// Calculate total time tracked towards tickets in the period (for this agent)
|
||||
$sql_time = mysqli_query($mysqli, "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(ticket_reply_time_worked))) as total_time FROM ticket_replies LEFT JOIN tickets ON tickets.ticket_id = ticket_replies.ticket_reply_ticket_id WHERE YEAR(ticket_created_at) = $year AND ticket_reply_by = $user_id AND ticket_reply_time_worked IS NOT NULL");
|
||||
$row = mysqli_fetch_array($sql_time);
|
||||
$ticket_total_time_worked = nullable_htmlentities($row['total_time']);
|
||||
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $user_name; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_raised_count; ?></td>
|
||||
<td class="text-right"><?php echo $tickets_touched; ?></td>
|
||||
<td class="text-right"><?php echo $ticket_total_time_worked; ?></td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TODO: Monthly version of this report -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
|
||||
Reference in New Issue
Block a user