89 Commits

Author SHA1 Message Date
wrongecho
3917e66fd8 Better error handling for undefined/non-existent asset IDs 2025-11-02 17:17:37 +00:00
wrongecho
9f48e2d9f0 Better error handling for undefined/non-existent asset IDs 2025-11-02 17:14:01 +00:00
wrongecho
215eadcf2b Better error handling for undefined/non-existent asset IDs 2025-11-02 17:12:03 +00:00
johnnyq
d3d706ea68 Added ticket details to the search query in global search tickets 2025-11-01 16:28:23 -04:00
johnnyq
8268761ef4 Add Recurring Invoice Reference along with a link in Invoices 2025-11-01 16:17:11 -04:00
wrongecho
2850c35bdc Flag duplicate clients/leads when using the client_add modal 2025-11-01 18:48:23 +00:00
wrongecho
24d8635dac Invoice product autocomplete - search product code as well as name 2025-11-01 17:59:12 +00:00
johnnyq
8314a115bb Migrate Add Asset to the new ajax-modal 2025-10-30 19:05:37 -04:00
johnnyq
b8e2423dbd Mugrated Payment Modals from invoice folder to payment modal folder 2025-10-30 14:46:49 -04:00
johnnyq
52c67f4139 Remove unused budget code 2025-10-30 14:29:51 -04:00
johnnyq
e895156d03 Fix TinyMCE not working on bulk create tickets and sort Categories ASC and fix assign to 2025-10-30 14:06:09 -04:00
johnnyq
89abc18465 Migrated Contact Add to the ajax-modal 2025-10-30 13:58:10 -04:00
johnnyq
355dfbbb25 [Feature] Create Recurring Ticket - Add Asset Type Optgroups on asset selection along with make, model and assigned contact 2025-10-29 19:14:21 -04:00
johnnyq
6d15640ae4 [Feature] Recurring Ticket - Add Three Day and Biweekly to the Frequency options 2025-10-29 18:15:21 -04:00
johnnyq
ad4ab5a54c Fix in old add ticket 2025-10-29 17:50:37 -04:00
johnnyq
3c5c86c4c5 Fix Issue with user not showing up in add ticket and recurring ticket, Also fixed the sort from DESC to ASC in some areas with user select 2025-10-29 17:49:39 -04:00
johnnyq
09b91c8826 [Feature] Recurring Tickets - Add Category, Assigned Agent and Billable Status filters 2025-10-29 17:13:52 -04:00
johnnyq
13ea48bff8 Seperate out recurring expenses and expenses into their own post file 2025-10-29 16:21:56 -04:00
johnnyq
26bb430d6e Seperate out posts into payment, invoice and recurring invoice instead of them all being under invoice post file 2025-10-29 16:18:32 -04:00
johnnyq
82da54740f Moved recurring ticket posts to its own post file 2025-10-29 15:58:04 -04:00
johnnyq
e02b10d12a [Feature] Added Billable column in recurring ticket list view along with bulk actions to set priority, agent, billable status, category and next run date 2025-10-29 15:51:14 -04:00
johnnyq
1573045157 Sort recurring tickets by Next Run Date instead of subject, and Swap Client column with Netrun column so Client column is last and next run date is first 2025-10-29 12:25:02 -04:00
johnnyq
bf31c333a6 Migrate Add Client Modal to the new Ajax Modal 2025-10-28 16:56:27 -04:00
johnnyq
4229bca978 Major UI Work on Contact Details Modal Always Display common details at the top with the nav underneath. 2025-10-25 18:16:56 -04:00
johnnyq
13bd929755 Tidy up the contact details modal 2025-10-25 14:44:20 -04:00
johnnyq
7f6c0346af Add https:// prefix to vendor website field in vendor details modal 2025-10-25 13:09:25 -04:00
johnnyq
0387e66066 Added Sortable Task Count in Ticket Templates Listing view 2025-10-25 12:54:58 -04:00
johnnyq
04bae8dc37 Add Archive and Delete buttons to document details along with button titles to state what the button does, also added a from var to fix redirect behavior if deleting from document details go back to documents listing 2025-10-24 14:46:09 -04:00
johnnyq
559506fc90 Added Access Modules to view current modules and to allow custom modules for the future for use in custom code directories 2025-10-23 15:55:54 -04:00
johnnyq
f2b6d481a1 Feature: Add new date range picker to admin area mail queue audit log, app log 2025-10-23 13:30:22 -04:00
johnnyq
c66aa92365 Update All Side Nav Links to be absolute so the side bar includes can be navigatable when navs are included in custom code 2025-10-23 13:07:02 -04:00
johnnyq
e24ef68d8d Fix Deleting Recurring Ticket from asset details page due to missing CSRF Check token 2025-10-22 17:11:26 -04:00
johnnyq
0cacf83ae5 Fix Sending Email when Forcing a Recurring Invoice into an Invoice 2025-10-22 16:28:53 -04:00
johnnyq
2dc66b329b Fix Ajax Modal Link to referral category in Add Bulk Referral 2025-10-22 15:26:15 -04:00
johnnyq
10dc8ea2bf Wording update for client bulk modals 2025-10-22 14:53:43 -04:00
johnnyq
303f9174c9 Added Bulk Create Tickets for Clients 2025-10-22 14:50:50 -04:00
johnnyq
c5dd5f2b6f Add Clause to not collapse advanced filter on all time aka if date from is set to the default 1970-01-01 2025-10-20 18:16:39 -04:00
johnnyq
ab77705ca2 Feature: Replace old date range to Date Range Picker JS for better date from/to handling 2025-10-20 18:04:00 -04:00
johnnyq
10c89ebf73 Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-10-16 11:43:37 -04:00
johnnyq
ecce994921 Used status var unstead of get status var for checkall 2025-10-16 11:43:26 -04:00
wrongecho
5dd4f5ea62 New mail parser:
- bugfix .eml not being generated
- include the message when notifying the tech of a reply
2025-10-16 16:32:37 +01:00
wrongecho
93bb5db019 typo 2025-10-15 21:56:21 +01:00
wrongecho
65ff008ccf Bugfix - Email not including ticket guest key 2025-10-15 15:36:07 +01:00
wrongecho
f0c48d23fe Add html code plugin + button to tinymceticket 2025-10-15 15:27:56 +01:00
wrongecho
975b52a43d Time tracking - show H/M/S placeholders if timer auto-start is disabled 2025-10-15 12:29:26 +01:00
wrongecho
079b0d5024 Asset import - allow importing notes 2025-10-15 10:32:16 +01:00
wrongecho
99ccb12b8c Allow importing TOTP credential info 2025-10-15 10:31:59 +01:00
wrongecho
0bb7d24e07 Allow importing TOTP credential info 2025-10-15 10:18:44 +01:00
wrongecho
b7a9f9ea38 When exporting credential info, include the TOTP secret 2025-10-15 10:12:14 +01:00
wrongecho
21aee98f9f Fix checkAll ticket box not showing when status wasn't set - should only be hidden for the closed view 2025-10-15 09:57:32 +01:00
wrongecho
9a5a4be64a When archiving a client, cancel recurring invoices 2025-10-15 09:20:08 +01:00
wrongecho
db7f8501d0 When archiving a client, cancel recurring invoices 2025-10-15 09:18:53 +01:00
johnnyq
61d15cbf9e Remove non existent seatch column recurring ticket prefix 2025-10-14 16:07:08 -04:00
johnnyq
39c9c695f1 Allow searching tickets with ticketprefix and number combo in Global search 2025-10-14 15:59:29 -04:00
johnnyq
d97654581b Add 30 Day wording to Expiring Domain and Certificates in dashboard 2025-10-12 13:34:27 -04:00
johnnyq
2ee70fd3a8 Update .htaccess 2025-10-09 19:23:48 -04:00
johnnyq
b336ec4188 Revert setup restore to a saner version 2025-10-09 19:14:31 -04:00
johnnyq
c77e1be1c3 Try to fix uploads 2025-10-09 19:00:02 -04:00
johnnyq
986f688468 another Attempt at restore 2025-10-09 18:49:54 -04:00
johnnyq
1d9429b762 Another attempt at restore 2025-10-09 18:27:35 -04:00
johnnyq
d122d90a47 Remove CSRF check 2025-10-09 18:11:16 -04:00
johnnyq
2c534d4d20 Attempt to fix uploads and writing to config file during setup 2025-10-09 18:10:21 -04:00
johnnyq
b7e0e5c5eb Fix setup complete flag 2025-10-09 13:00:00 -04:00
johnnyq
2915b12181 Remove temp CSRF check on setup 2025-10-09 12:43:28 -04:00
johnnyq
ed589ef65b Update Backup / Restore, now streams backup and restore to disk instead of memory causing memory to run out, sets timeout limit to unlimited, checks backup file contents for anything bad, use php instead shell exec for import of db, added .htaccess for apache to prevent php execution in /uploads/ directory as this is intended for file download only 2025-10-09 12:28:38 -04:00
johnnyq
fbf3346052 Update Changelog 2025-10-08 17:30:19 -04:00
johnnyq
3ff206f84d Add .htaccess in cron 2025-10-08 17:25:03 -04:00
johnnyq
a3b0fce961 Fix login_microsoft 2025-10-08 17:19:17 -04:00
johnnyq
8130280b35 Fix edit from contact details modal 2025-10-08 17:12:23 -04:00
johnnyq
fea3020d9a Add powered by ITFlow in Guest Section 2025-10-08 15:29:06 -04:00
johnnyq
1eb9d163fa Updated Changelog 2025-10-08 14:50:34 -04:00
johnnyq
e3e7c2e38b Add Signature in ticket reply POST dont add a signature if Internal 2025-10-08 14:48:13 -04:00
johnnyq
27e1d6a9cd remove net terms in quote add jquery to guest header 2025-10-08 01:18:55 -04:00
johnnyq
2ec4cdc4fb Ceated inc_all_guest.php and modulaized the guest header.php removed guest footer and used the global footer.php as they were very similar 2025-10-08 01:00:48 -04:00
johnnyq
35a7506c26 Copy crons from /scripts to /cron, added custom directories for api/v1/, /setup, /cron and /scripts 2025-10-07 13:55:54 -04:00
johnnyq
16242be74e Update Client Nav to use Absolute links and updated more of the inc_alls to use Document Server Root 2025-10-07 13:44:08 -04:00
johnnyq
3fcbe440d3 Fix Missing Missing Country code in Guest View Ticket 2025-10-07 12:34:26 -04:00
johnnyq
4ef0755039 Update Guest header and footer to use Server Document Root var 2025-10-06 17:07:19 -04:00
johnnyq
a4ed906dd1 Update modal footer and header to user SERVER Document root with absolute path intead of relative 2025-10-06 15:13:52 -04:00
johnnyq
416a8d9a94 Fix to properly redirect to the setup page if config_enable_setup is not set or is 1 2025-10-06 14:19:49 -04:00
wrongecho
d8803aaac2 prevent open redirects upon agent login 2025-10-06 16:32:42 +01:00
wrongecho
01f6615ca0 rm test 2025-10-06 16:13:08 +01:00
johnnyq
fd93ee3263 Allow HTML for signatures 2025-10-04 19:20:34 -04:00
johnnyq
32bfd298a1 Added Project Edit Function for Ticket 2025-10-03 17:37:25 -04:00
johnnyq
5de2e7a3bd If imap Encryption is blank then use notls in the ticket mail parser 2025-10-03 11:36:27 -04:00
johnnyq
6e8c133a99 Fix Regressions in Vendor Templates updated path from ../user/post to ../agent/post 2025-10-03 11:25:48 -04:00
johnnyq
956f18430b Fix Microsoft SSO Login in Client Portal, fix ticket templates due to regression from changing from user to agent 2025-10-03 11:12:48 -04:00
johnnyq
76c9933baf Update imap and smtp providers to allow empty string if empty do not execute mail queue 2025-10-02 14:28:43 -04:00
johnnyq
6c6a988c2b Fix custom Favicon 2025-10-02 11:42:30 -04:00
140 changed files with 9213 additions and 6094 deletions

9
.gitignore vendored
View File

@@ -34,5 +34,14 @@ client/custom/*
!client/custom/readme.php !client/custom/readme.php
guest/custom/* guest/custom/*
!guest/custom/readme.php !guest/custom/readme.php
cron/custom/*
!cron/custom/readme.php
scripts/custom/*
!scripts/custom/readme.php
setup/custom/*
!setup/custom/readme.php
api/v1/custom/*
!api/v1/custom/readme.php
.zed .zed

View File

@@ -2,6 +2,30 @@
This file documents all notable changes made to ITFlow. This file documents all notable changes made to ITFlow.
## [25.10.1]
- Deprecation Notice: `/scripts/cron_mail_queue.php` , `/scripts/cron_ticket_email_parser.php` , `/scripts/cron.php` `/scripts/cron_domain_refresher.php`, `/scripts/cron_certificate_refresher.php` are being phased out. Please transition to `/cron/mail_queue.php` , `/cron/ticket_email_parser.php`, `/cron/cron.php`, `/cron/domain_refresher.php`, `/cron/certificate_refresher.php` These older scripts will be removed in the November 25.11 release—update accordingly. 25.10.1 installs have the script already configured.
### Fixes
- Fix regression missing custom Favicon.
- Update SMTP and IMAP provider to allow for empty strings, empty means disabled.
- Fix Client portal Microsoft SSO Logins.
- Fix regression in Vendor Templates.
- Fix refression in some broken links from user to agent.
- Fix Project edit.
- Prevent open redirects upon agent login.
- Fix regression on switching to Webklex IMAP to allow for no SSL/TLS in IMAP.
- Fix Setup Redirect not behaving properly when setup hasnt been performed.
- Added Server Document Root Var to several includes, headers, footers files to allow includes from deeper directory strutures such as the new custom directories.
- Fix edit contact in contact details.
- Add .htaccess to /cron/.
### Added / Changed
- Support for HTML Signatures.
- Add Edit Project Functionality in a ticket.
- Added more custom locations: /cron/custom/, /scripts/custom/, /api/v1/custom/, /setup/custom/.
- Copied `/scripts/cron.php` `/scripts/cron_domain_refresher.php`, `/scripts/cron_certificate_refresher.php` to `/cron/cron.php`, `/cron/domain_refresher.php`, `/cron/certificate_refresher.php`. See Above!
- Signatures is now handled in post ticket reply on Public Comments only.
## [25.10] ## [25.10]
### Breaking Changes ### Breaking Changes

View File

@@ -97,34 +97,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -159,34 +159,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4027,10 +4027,16 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.5'"); mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.5'");
} }
// if (CURRENT_DATABASE_VERSION == '2.3.4') { if (CURRENT_DATABASE_VERSION == '2.3.5') {
// // Insert queries here required to update to DB version 2.3.4 mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_smtp_provider` `config_smtp_provider` VARCHAR(200) DEFAULT NULL");
mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_imap_provider` `config_imap_provider` VARCHAR(200) DEFAULT NULL");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.6'");
}
// if (CURRENT_DATABASE_VERSION == '2.3.5') {
// // Insert queries here required to update to DB version 2.3.5
// // Then, update the database to the next sequential version // // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.5'"); // mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.6'");
// } // }
} else { } else {

View File

@@ -1,16 +1,16 @@
<?php <?php
require_once "../config.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once "../functions.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once "../includes/check_login.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once "../includes/page_title.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
if (!isset($session_is_admin) || !$session_is_admin) { if (!isset($session_is_admin) || !$session_is_admin) {
exit(WORDING_ROLECHECK_FAILED . "<br>Tell your admin: Your role does not have admin access."); exit(WORDING_ROLECHECK_FAILED . "<br>Tell your admin: Your role does not have admin access.");
} }
require_once "../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once "../includes/top_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once "includes/side_nav.php"; require_once 'includes/side_nav.php';
require_once "../includes/inc_wrapper.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once "../includes/inc_alert_feedback.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once "../includes/filter_header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
require_once "../includes/app_version.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/app_version.php';

View File

@@ -1,6 +1,6 @@
<!-- Main Sidebar Container --> <!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none"> <aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none">
<a class="brand-link pb-1 mt-1" href="../agent/<?php echo $config_start_page ?>"> <a class="brand-link pb-1 mt-1" href="/agent/<?php echo $config_start_page ?>">
<p class="h6"> <p class="h6">
<i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i> <i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
<span class="brand-text"> <span class="brand-text">
@@ -14,21 +14,27 @@
<!-- Sidebar Menu --> <!-- Sidebar Menu -->
<nav> <nav>
<ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" data-accordion="false"> <ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" data-accordion="false">
<!-- ACCESS Section --> <li class="nav-header">ACCESS</li>
<li class="nav-item"> <li class="nav-item">
<a href="users.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "users.php") {echo "active";} ?>"> <a href="/admin/users.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "users.php") {echo "active";} ?>">
<i class="nav-icon fas fa-users"></i> <i class="nav-icon fas fa-users"></i>
<p>Users</p> <p>Users</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="roles.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "roles.php") {echo "active";} ?>"> <a href="/admin/roles.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "roles.php") {echo "active";} ?>">
<i class="nav-icon fas fa-user-shield"></i> <i class="nav-icon fas fa-user-shield"></i>
<p>Roles</p> <p>Roles</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="api_keys.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "api_keys.php") {echo "active";} ?>"> <a href="/admin/modules.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "modules.php") {echo "active";} ?>">
<i class="nav-icon fas fa-puzzle-piece"></i>
<p>Modules</p>
</a>
</li>
<li class="nav-item">
<a href="/admin/api_keys.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "api_keys.php") {echo "active";} ?>">
<i class="nav-icon fas fa-key"></i> <i class="nav-icon fas fa-key"></i>
<p>API Keys</p> <p>API Keys</p>
</a> </a>
@@ -36,51 +42,51 @@
<li class="nav-header">TAGS & CATEGORIES</li> <li class="nav-header">TAGS & CATEGORIES</li>
<li class="nav-item"> <li class="nav-item">
<a href="tag.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tag.php' ? 'active' : ''); ?>"> <a href="/admin/tag.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tag.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-tags"></i> <i class="nav-icon fas fa-tags"></i>
<p>Tags</p> <p>Tags</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="category.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'category.php' ? 'active' : ''); ?>"> <a href="/admin/category.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'category.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-list-ul"></i> <i class="nav-icon fas fa-list-ul"></i>
<p>Categories</p> <p>Categories</p>
</a> </a>
</li> </li>
<?php if ($config_module_enable_accounting) { ?> <?php if ($config_module_enable_accounting) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="tax.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tax.php' ? 'active' : ''); ?>"> <a href="/admin/tax.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tax.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-balance-scale"></i> <i class="nav-icon fas fa-balance-scale"></i>
<p>Taxes</p> <p>Taxes</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'payment_method.php' ? 'active' : ''); ?>"> <a href="/admin/payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'payment_method.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-hand-holding-usd"></i> <i class="nav-icon fas fa-hand-holding-usd"></i>
<p>Payment Methods</p> <p>Payment Methods</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="payment_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'payment_provider.php' ? 'active' : ''); ?>"> <a href="/admin/payment_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'payment_provider.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i> <i class="nav-icon far fa-credit-card"></i>
<p>Payment Providers</p> <p>Payment Providers</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="saved_payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'saved_payment_method.php' ? 'active' : ''); ?>"> <a href="/admin/saved_payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'saved_payment_method.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i> <i class="nav-icon far fa-credit-card"></i>
<p>Saved Payments</p> <p>Saved Payments</p>
</a> </a>
</li> </li>
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="ai_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_provider.php' ? 'active' : ''); ?>"> <a href="/admin/ai_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_provider.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-robot"></i> <i class="nav-icon fas fa-robot"></i>
<p>AI Providers</p> <p>AI Providers</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="ai_model.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_model.php' ? 'active' : ''); ?>"> <a href="/admin/ai_model.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_model.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-robot"></i> <i class="nav-icon fas fa-robot"></i>
<p>AI Models</p> <p>AI Models</p>
</a> </a>
@@ -88,14 +94,14 @@
<?php if ($config_module_enable_ticketing) { ?> <?php if ($config_module_enable_ticketing) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="ticket_status.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ticket_status.php' ? 'active' : ''); ?>"> <a href="/admin/ticket_status.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ticket_status.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-info-circle"></i> <i class="nav-icon fas fa-info-circle"></i>
<p>Ticket Statuses</p> <p>Ticket Statuses</p>
</a> </a>
</li> </li>
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="custom_link.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'custom_link.php' ? 'active' : ''); ?>"> <a href="/admin/custom_link.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'custom_link.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-external-link-alt"></i> <i class="nav-icon fas fa-external-link-alt"></i>
<p>Custom Links</p> <p>Custom Links</p>
</a> </a>
@@ -105,31 +111,31 @@
<li class="nav-header">TEMPLATES</li> <li class="nav-header">TEMPLATES</li>
<li class="nav-item"> <li class="nav-item">
<a href="project_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['project_template.php', 'project_template_details.php']) ? 'active' : ''); ?>"> <a href="/admin/project_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['project_template.php', 'project_template_details.php']) ? 'active' : ''); ?>">
<i class="nav-icon fas fa-project-diagram"></i> <i class="nav-icon fas fa-project-diagram"></i>
<p>Project Templates</p> <p>Project Templates</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="ticket_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['ticket_template.php', 'ticket_template_details.php']) ? 'active' : ''); ?>"> <a href="/admin/ticket_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['ticket_template.php', 'ticket_template_details.php']) ? 'active' : ''); ?>">
<i class="nav-icon fas fa-life-ring"></i> <i class="nav-icon fas fa-life-ring"></i>
<p>Ticket Templates</p> <p>Ticket Templates</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="vendor_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'vendor_template.php' ? 'active' : ''); ?>"> <a href="/admin/vendor_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'vendor_template.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-building"></i> <i class="nav-icon fas fa-building"></i>
<p>Vendor Templates</p> <p>Vendor Templates</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="software_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'software_template.php' ? 'active' : ''); ?>"> <a href="/admin/software_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'software_template.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-rocket"></i> <i class="nav-icon fas fa-rocket"></i>
<p>License Templates</p> <p>License Templates</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="document_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['document_template.php', 'document_template_details.php']) ? 'active' : ''); ?>"> <a href="/admin/document_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['document_template.php', 'document_template_details.php']) ? 'active' : ''); ?>">
<i class="nav-icon fas fa-file"></i> <i class="nav-icon fas fa-file"></i>
<p>Document Templates</p> <p>Document Templates</p>
</a> </a>
@@ -139,37 +145,37 @@
<li class="nav-header">MAINTENANCE</li> <li class="nav-header">MAINTENANCE</li>
<li class="nav-item"> <li class="nav-item">
<a href="mail_queue.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'mail_queue.php' ? 'active' : ''); ?>"> <a href="/admin/mail_queue.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'mail_queue.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-mail-bulk"></i> <i class="nav-icon fas fa-mail-bulk"></i>
<p>Mail Queue</p> <p>Mail Queue</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="audit_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'audit_log.php' ? 'active' : ''); ?>"> <a href="/admin/audit_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'audit_log.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-history"></i> <i class="nav-icon fas fa-history"></i>
<p>Audit Logs</p> <p>Audit Logs</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="app_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'app_log.php' ? 'active' : ''); ?>"> <a href="/admin/app_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'app_log.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-history"></i> <i class="nav-icon fas fa-history"></i>
<p>App Logs</p> <p>App Logs</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="backup.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'backup.php' ? 'active' : ''); ?>"> <a href="/admin/backup.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'backup.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-cloud-upload-alt"></i> <i class="nav-icon fas fa-cloud-upload-alt"></i>
<p>Backup</p> <p>Backup</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="debug.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'debug.php' ? 'active' : ''); ?>"> <a href="/admin/debug.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'debug.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-bug"></i> <i class="nav-icon fas fa-bug"></i>
<p>Debug</p> <p>Debug</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="update.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'update.php' ? 'active' : ''); ?>"> <a href="/admin/update.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'update.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-download"></i> <i class="nav-icon fas fa-download"></i>
<p>Update</p> <p>Update</p>
</a> </a>
@@ -185,56 +191,56 @@
</a> </a>
<ul class="nav nav-treeview"> <ul class="nav nav-treeview">
<li class="nav-item"> <li class="nav-item">
<a href="settings_company.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_company.php' ? 'active' : ''); ?>"> <a href="/admin/settings_company.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_company.php' ? 'active' : ''); ?>">
<i class="nav-icon fa fa-briefcase"></i> <i class="nav-icon fa fa-briefcase"></i>
<p>Company Details</p> <p>Company Details</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_localization.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_localization.php' ? 'active' : ''); ?>"> <a href="/admin/settings_localization.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_localization.php' ? 'active' : ''); ?>">
<i class="nav-icon fa fa-globe"></i> <i class="nav-icon fa fa-globe"></i>
<p>Localization</p> <p>Localization</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_theme.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_theme.php' ? 'active' : ''); ?>"> <a href="/admin/settings_theme.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_theme.php' ? 'active' : ''); ?>">
<i class="nav-icon fa fa-paint-brush"></i> <i class="nav-icon fa fa-paint-brush"></i>
<p>Theme</p> <p>Theme</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_security.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_security.php' ? 'active' : ''); ?>"> <a href="/admin/settings_security.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_security.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-shield-alt"></i> <i class="nav-icon fas fa-shield-alt"></i>
<p>Security</p> <p>Security</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_mail.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_mail.php' ? 'active' : ''); ?>"> <a href="/admin/settings_mail.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_mail.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-envelope"></i> <i class="nav-icon far fa-envelope"></i>
<p>Mail</p> <p>Mail</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_notification.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_notification.php' ? 'active' : ''); ?>"> <a href="/admin/settings_notification.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_notification.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-bell"></i> <i class="nav-icon far fa-bell"></i>
<p>Notifications</p> <p>Notifications</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_default.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_default.php' ? 'active' : ''); ?>"> <a href="/admin/settings_default.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_default.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-cogs"></i> <i class="nav-icon fas fa-cogs"></i>
<p>Defaults</p> <p>Defaults</p>
</a> </a>
</li> </li>
<?php if ($config_module_enable_accounting) { ?> <?php if ($config_module_enable_accounting) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="settings_invoice.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_invoice.php' ? 'active' : ''); ?>"> <a href="/admin/settings_invoice.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_invoice.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-file-invoice"></i> <i class="nav-icon fas fa-file-invoice"></i>
<p>Invoice</p> <p>Invoice</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_quote.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_quote.php' ? 'active' : ''); ?>"> <a href="/admin/settings_quote.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_quote.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-comment-dollar"></i> <i class="nav-icon fas fa-comment-dollar"></i>
<p>Quote</p> <p>Quote</p>
</a> </a>
@@ -242,13 +248,13 @@
<?php } ?> <?php } ?>
<?php if ($config_module_enable_ticketing) { ?> <?php if ($config_module_enable_ticketing) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="settings_project.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_project.php' ? 'active' : ''); ?>"> <a href="/admin/settings_project.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_project.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-project-diagram"></i> <i class="nav-icon fas fa-project-diagram"></i>
<p>Project</p> <p>Project</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_ticket.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_ticket.php' ? 'active' : ''); ?>"> <a href="/admin/settings_ticket.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_ticket.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-life-ring"></i> <i class="nav-icon fas fa-life-ring"></i>
<p>Ticket</p> <p>Ticket</p>
</a> </a>
@@ -257,20 +263,20 @@
<!-- Currently the only integration is the client portal SSO --> <!-- Currently the only integration is the client portal SSO -->
<?php if ($config_client_portal_enable) { ?> <?php if ($config_client_portal_enable) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="identity_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'identity_provider.php' ? 'active' : ''); ?>"> <a href="/admin/identity_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'identity_provider.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-fingerprint"></i> <i class="nav-icon fas fa-fingerprint"></i>
<p>Identity Provider</p> <p>Identity Provider</p>
</a> </a>
</li> </li>
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="settings_telemetry.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_telemetry.php' ? 'active' : ''); ?>"> <a href="/admin/settings_telemetry.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_telemetry.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-satellite-dish"></i> <i class="nav-icon fas fa-satellite-dish"></i>
<p>Telemetry</p> <p>Telemetry</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="settings_module.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_module.php' ? 'active' : ''); ?>"> <a href="/admin/settings_module.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_module.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-cube"></i> <i class="nav-icon fas fa-cube"></i>
<p>Modules</p> <p>Modules</p>
</a> </a>

View File

@@ -53,34 +53,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

113
admin/modules.php Normal file
View File

@@ -0,0 +1,113 @@
<?php
// Default Column Sortby Filter
$sort = "module_name";
$order = "DESC";
require_once "includes/inc_all_admin.php";
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM modules
WHERE (module_name LIKE '%$q%' OR module_description LIKE '%$q%')
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-puzzle-piece mr-2"></i>Access Modules</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/module/module_add.php">
<i class="fas fa-fw fa-plus mr-2"></i>New Module
</button>
</div>
</div>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {echo stripslashes(nullable_htmlentities($q));} ?>" placeholder="Search Modules">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=module_name&order=<?php echo $disp; ?>">
Module <?php if ($sort == 'module_name') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$module_id = intval($row['module_id']);
$module_name = nullable_htmlentities($row['module_name']);
$module_description = nullable_htmlentities($row['module_description']);
?>
<tr>
<td>
<a href="#" <?php if ($module_id > 6) { ?> class="ajax-modal" data-modal-url="modals/modules/module_edit.php?id=<?= $module_id ?>" <?php } ?>>
<strong class="text-dark"><?= $module_name ?></strong>
</a>
<div class="text-secondary"><?= $module_description ?></div>
</td>
<td>
<?php if ($module_id > 6) { ?>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/module/module_edit.php?id=<?= $module_id ?>">
<i class="fas fa-fw fa-user-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_module=<?= $module_id ?>&csrf_token=<?= $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Delete
</a>
</div>
</div>
<?php } else { echo "<p class='text-center'>N/A Predefined</p>"; } ?>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
<?php require_once "../includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "../includes/footer.php";

View File

@@ -2,36 +2,170 @@
/* /*
* ITFlow - GET/POST request handler for DB / master key backup * ITFlow - GET/POST request handler for DB / master key backup
* Rewritten with streaming SQL dump, component checksums, safer zipping, and better headers.
*/ */
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed"); defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
require_once "../includes/app_version.php"; require_once "../includes/app_version.php";
if (isset($_GET['download_backup'])) { // --- Optional performance levers for big backups ---
@set_time_limit(0);
if (function_exists('ini_set')) {
@ini_set('memory_limit', '1024M');
}
validateCSRFToken($_GET['csrf_token']); /**
* Write a line to a file handle with newline.
*/
function fwrite_ln($fh, string $s): void {
fwrite($fh, $s);
fwrite($fh, PHP_EOL);
}
$timestamp = date('YmdHis'); /**
$baseName = "itflow_$timestamp"; * Stream a SQL dump of schema and data into $sqlFile.
* - Tables first (DROP + CREATE + INSERTs)
* - Views (DROP VIEW + CREATE VIEW)
* - Triggers (DROP TRIGGER + CREATE TRIGGER)
*
* NOTE: Routines/events are not dumped here. Add if needed.
*/
function dump_database_streaming(mysqli $mysqli, string $sqlFile): void {
$fh = fopen($sqlFile, 'wb');
if (!$fh) {
http_response_code(500);
exit("Cannot open dump file");
}
// === 0. Scoped cleanup === // Preamble
$cleanupFiles = []; fwrite_ln($fh, "-- UTF-8 + Foreign Key Safe Dump");
fwrite_ln($fh, "SET NAMES 'utf8mb4';");
fwrite_ln($fh, "SET FOREIGN_KEY_CHECKS = 0;");
fwrite_ln($fh, "SET UNIQUE_CHECKS = 0;");
fwrite_ln($fh, "SET AUTOCOMMIT = 0;");
fwrite_ln($fh, "");
$registerTempFileForCleanup = function ($file) use (&$cleanupFiles) { // Gather tables and views
$cleanupFiles[] = $file; $tables = [];
}; $views = [];
register_shutdown_function(function () use (&$cleanupFiles) { $res = $mysqli->query("SHOW FULL TABLES");
foreach ($cleanupFiles as $file) { if (!$res) {
if (is_file($file)) { fclose($fh);
@unlink($file); error_log("MySQL Error (SHOW FULL TABLES): " . $mysqli->error);
http_response_code(500);
exit("Error retrieving tables.");
}
while ($row = $res->fetch_array(MYSQLI_NUM)) {
$name = $row[0];
$type = strtoupper($row[1] ?? '');
if ($type === 'VIEW') {
$views[] = $name;
} else {
$tables[] = $name;
} }
} }
}); $res->close();
// === 1. Local helper function: zipFolder // --- TABLES: structure and data ---
$zipFolder = function ($folderPath, $zipFilePath) { foreach ($tables as $table) {
$createRes = $mysqli->query("SHOW CREATE TABLE `{$mysqli->real_escape_string($table)}`");
if (!$createRes) {
error_log("MySQL Error (SHOW CREATE TABLE $table): " . $mysqli->error);
// continue to next table
continue;
}
$createRow = $createRes->fetch_assoc();
$createSQL = array_values($createRow)[1] ?? '';
$createRes->close();
fwrite_ln($fh, "-- ----------------------------");
fwrite_ln($fh, "-- Table structure for `{$table}`");
fwrite_ln($fh, "-- ----------------------------");
fwrite_ln($fh, "DROP TABLE IF EXISTS `{$table}`;");
fwrite_ln($fh, $createSQL . ";");
fwrite_ln($fh, "");
// Dump data in a streaming fashion
$dataRes = $mysqli->query("SELECT * FROM `{$mysqli->real_escape_string($table)}`", MYSQLI_USE_RESULT);
if ($dataRes) {
$wroteHeader = false;
while ($row = $dataRes->fetch_assoc()) {
if (!$wroteHeader) {
fwrite_ln($fh, "-- Dumping data for table `{$table}`");
$wroteHeader = true;
}
$cols = array_map(fn($c) => '`' . $mysqli->real_escape_string($c) . '`', array_keys($row));
$vals = array_map(
function ($v) use ($mysqli) {
return is_null($v) ? "NULL" : "'" . $mysqli->real_escape_string($v) . "'";
},
array_values($row)
);
fwrite_ln($fh, "INSERT INTO `{$table}` (" . implode(", ", $cols) . ") VALUES (" . implode(", ", $vals) . ");");
}
$dataRes->close();
if ($wroteHeader) fwrite_ln($fh, "");
}
}
// --- VIEWS ---
foreach ($views as $view) {
$escView = $mysqli->real_escape_string($view);
$cRes = $mysqli->query("SHOW CREATE VIEW `{$escView}`");
if ($cRes) {
$row = $cRes->fetch_assoc();
$createView = $row['Create View'] ?? '';
$cRes->close();
fwrite_ln($fh, "-- ----------------------------");
fwrite_ln($fh, "-- View structure for `{$view}`");
fwrite_ln($fh, "-- ----------------------------");
fwrite_ln($fh, "DROP VIEW IF EXISTS `{$view}`;");
// Ensure statement ends with semicolon
if (!str_ends_with($createView, ';')) $createView .= ';';
fwrite_ln($fh, $createView);
fwrite_ln($fh, "");
}
}
// --- TRIGGERS ---
$tRes = $mysqli->query("SHOW TRIGGERS");
if ($tRes) {
while ($t = $tRes->fetch_assoc()) {
$triggerName = $t['Trigger'];
$escTrig = $mysqli->real_escape_string($triggerName);
$crt = $mysqli->query("SHOW CREATE TRIGGER `{$escTrig}`");
if ($crt) {
$row = $crt->fetch_assoc();
$createTrig = $row['SQL Original Statement'] ?? ($row['Create Trigger'] ?? '');
$crt->close();
fwrite_ln($fh, "-- ----------------------------");
fwrite_ln($fh, "-- Trigger for `{$triggerName}`");
fwrite_ln($fh, "-- ----------------------------");
fwrite_ln($fh, "DROP TRIGGER IF EXISTS `{$triggerName}`;");
if (!str_ends_with($createTrig, ';')) $createTrig .= ';';
fwrite_ln($fh, $createTrig);
fwrite_ln($fh, "");
}
}
$tRes->close();
}
// Postamble
fwrite_ln($fh, "SET FOREIGN_KEY_CHECKS = 1;");
fwrite_ln($fh, "SET UNIQUE_CHECKS = 1;");
fwrite_ln($fh, "COMMIT;");
fclose($fh);
}
/**
* Zip a folder to $zipFilePath, skipping symlinks and dot-entries.
*/
function zipFolderStrict(string $folderPath, string $zipFilePath): void {
$zip = new ZipArchive(); $zip = new ZipArchive();
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) { if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
error_log("Failed to open zip file: $zipFilePath"); error_log("Failed to open zip file: $zipFilePath");
@@ -39,30 +173,57 @@ if (isset($_GET['download_backup'])) {
exit("Internal Server Error: Cannot open zip archive."); exit("Internal Server Error: Cannot open zip archive.");
} }
$folderPath = realpath($folderPath); $folderReal = realpath($folderPath);
if (!$folderPath) { if (!$folderReal || !is_dir($folderReal)) {
error_log("Invalid folder path: $folderPath"); // Create an empty archive if uploads folder doesn't exist yet
http_response_code(500); $zip->close();
exit("Internal Server Error: Invalid folder path."); return;
} }
$files = new RecursiveIteratorIterator( $files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($folderPath), new RecursiveDirectoryIterator($folderReal, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY RecursiveIteratorIterator::LEAVES_ONLY
); );
foreach ($files as $file) { foreach ($files as $file) {
if (!$file->isDir()) { /** @var SplFileInfo $file */
if ($file->isDir()) continue;
if ($file->isLink()) continue; // skip symlinks
$filePath = $file->getRealPath(); $filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen($folderPath) + 1); if ($filePath === false) continue;
$zip->addFile($filePath, $relativePath);
// ensure path is inside the folder boundary
if (strpos($filePath, $folderReal . DIRECTORY_SEPARATOR) !== 0 && $filePath !== $folderReal) {
continue;
} }
$relativePath = substr($filePath, strlen($folderReal) + 1);
$zip->addFile($filePath, $relativePath);
} }
$zip->close(); $zip->close();
}; }
// === 2. Create all temp files if (isset($_GET['download_backup'])) {
validateCSRFToken($_GET['csrf_token']);
$timestamp = date('YmdHis');
$baseName = "itflow_{$timestamp}";
$downloadName = $baseName . ".zip";
// === Scoped cleanup of temp files ===
$cleanupFiles = [];
$registerTempFileForCleanup = function ($file) use (&$cleanupFiles) {
$cleanupFiles[] = $file;
};
register_shutdown_function(function () use (&$cleanupFiles) {
foreach ($cleanupFiles as $file) {
if (is_file($file)) { @unlink($file); }
}
});
// === Create temp files ===
$sqlFile = tempnam(sys_get_temp_dir(), $baseName . "_sql_"); $sqlFile = tempnam(sys_get_temp_dir(), $baseName . "_sql_");
$uploadsZip = tempnam(sys_get_temp_dir(), $baseName . "_uploads_"); $uploadsZip = tempnam(sys_get_temp_dir(), $baseName . "_uploads_");
$versionFile = tempnam(sys_get_temp_dir(), $baseName . "_version_"); $versionFile = tempnam(sys_get_temp_dir(), $baseName . "_version_");
@@ -70,117 +231,75 @@ if (isset($_GET['download_backup'])) {
foreach ([$sqlFile, $uploadsZip, $versionFile, $finalZip] as $f) { foreach ([$sqlFile, $uploadsZip, $versionFile, $finalZip] as $f) {
$registerTempFileForCleanup($f); $registerTempFileForCleanup($f);
chmod($f, 0600); @chmod($f, 0600);
} }
// === 3. Generate SQL Dump // === Generate SQL Dump (streaming) ===
$sqlContent = "-- UTF-8 + Foreign Key Safe Dump\n"; dump_database_streaming($mysqli, $sqlFile);
$sqlContent .= "SET NAMES 'utf8mb4';\n";
$sqlContent .= "SET foreign_key_checks = 0;\n\n";
$tables = []; // === Zip the uploads folder (strict) ===
$res = $mysqli->query("SHOW TABLES"); zipFolderStrict("../uploads", $uploadsZip);
if (!$res) {
error_log("MySQL Error: " . $mysqli->error);
exit("Error retrieving tables.");
}
while ($row = $res->fetch_row()) { // === Gather metadata & checksums ===
$tables[] = $row[0]; $commitHash = (function_exists('shell_exec') ? trim(shell_exec('git log -1 --format=%H 2>/dev/null')) : '') ?: 'N/A';
} $gitBranch = (function_exists('shell_exec') ? trim(shell_exec('git rev-parse --abbrev-ref HEAD 2>/dev/null')) : '') ?: 'N/A';
foreach ($tables as $table) { $dbSha = hash_file('sha256', $sqlFile) ?: 'N/A';
$createRes = $mysqli->query("SHOW CREATE TABLE `$table`"); $upSha = hash_file('sha256', $uploadsZip) ?: 'N/A';
if (!$createRes) {
error_log("MySQL Error: " . $mysqli->error);
continue;
}
$createRow = $createRes->fetch_assoc();
$createSQL = array_values($createRow)[1];
$sqlContent .= "\n-- ----------------------------\n";
$sqlContent .= "-- Table structure for `$table`\n";
$sqlContent .= "-- ----------------------------\n";
$sqlContent .= "DROP TABLE IF EXISTS `$table`;\n";
$sqlContent .= $createSQL . ";\n\n";
$dataRes = $mysqli->query("SELECT * FROM `$table`");
if ($dataRes && $dataRes->num_rows > 0) {
$sqlContent .= "-- Dumping data for table `$table`\n";
while ($row = $dataRes->fetch_assoc()) {
$columns = array_map(fn($col) => '`' . $mysqli->real_escape_string($col) . '`', array_keys($row));
$values = array_map(function ($val) use ($mysqli) {
return is_null($val) ? "NULL" : "'" . $mysqli->real_escape_string($val) . "'";
}, array_values($row));
$sqlContent .= "INSERT INTO `$table` (" . implode(", ", $columns) . ") VALUES (" . implode(", ", $values) . ");\n";
}
$sqlContent .= "\n";
}
}
$sqlContent .= "SET foreign_key_checks = 1;\n";
file_put_contents($sqlFile, $sqlContent);
// === 4. Zip the uploads folder
$zipFolder("../uploads", $uploadsZip);
// === 5. Create version.txt
$commitHash = trim(shell_exec('git log -1 --format=%H')) ?: 'N/A';
$gitBranch = trim(shell_exec('git rev-parse --abbrev-ref HEAD')) ?: 'N/A';
$versionContent = "ITFlow Backup Metadata\n"; $versionContent = "ITFlow Backup Metadata\n";
$versionContent .= "-----------------------------\n"; $versionContent .= "-----------------------------\n";
$versionContent .= "Generated: " . date('Y-m-d H:i:s') . "\n"; $versionContent .= "Generated: " . date('Y-m-d H:i:s') . "\n";
$versionContent .= "Backup File: " . basename($finalZip) . "\n"; $versionContent .= "Backup File: " . $downloadName . "\n";
$versionContent .= "Generated By: $session_name\n"; $versionContent .= "Generated By: " . ($session_name ?? 'Unknown User') . "\n";
$versionContent .= "Host: " . gethostname() . "\n"; $versionContent .= "Host: " . gethostname() . "\n";
$versionContent .= "Git Branch: $gitBranch\n"; $versionContent .= "Git Branch: $gitBranch\n";
$versionContent .= "Git Commit: $commitHash\n"; $versionContent .= "Git Commit: $commitHash\n";
$versionContent .= "ITFlow Version: " . (defined('APP_VERSION') ? APP_VERSION : 'Unknown') . "\n"; $versionContent .= "ITFlow Version: " . (defined('APP_VERSION') ? APP_VERSION : 'Unknown') . "\n";
$versionContent .= "Database Version: " . (defined('CURRENT_DATABASE_VERSION') ? CURRENT_DATABASE_VERSION : 'Unknown') . "\n"; $versionContent .= "Database Version: " . (defined('CURRENT_DATABASE_VERSION') ? CURRENT_DATABASE_VERSION : 'Unknown') . "\n";
$versionContent .= "Checksum (SHA256): \n"; $versionContent .= "Checksums (SHA256):\n";
$versionContent .= " db.sql: $dbSha\n";
$versionContent .= " uploads.zip: $upSha\n";
file_put_contents($versionFile, $versionContent); file_put_contents($versionFile, $versionContent);
@chmod($versionFile, 0600);
// === 6. Build final ZIP // === Build final ZIP ===
$final = new ZipArchive(); $final = new ZipArchive();
if ($final->open($finalZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) { if ($final->open($finalZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
error_log("Failed to create final zip: $finalZip"); error_log("Failed to create final zip: $finalZip");
http_response_code(500); http_response_code(500);
exit("Internal Server Error: Unable to create backup archive."); exit("Internal Server Error: Unable to create backup archive.");
} }
$final->addFile($sqlFile, "db.sql"); $final->addFile($sqlFile, "db.sql");
$final->addFile($uploadsZip, "uploads.zip"); $final->addFile($uploadsZip, "uploads.zip");
$final->addFile($versionFile, "version.txt"); $final->addFile($versionFile, "version.txt");
$final->close(); $final->close();
chmod($finalZip, 0600); @chmod($finalZip, 0600);
$checksum = hash_file('sha256', $finalZip); // === Serve final ZIP with a stable filename ===
file_put_contents($versionFile, $versionContent . "$checksum\n");
// === 7. Serve final ZIP
header('Content-Type: application/zip'); header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($finalZip) . '"'); header('X-Content-Type-Options: nosniff');
header('Content-Disposition: attachment; filename="' . $downloadName . '"');
header('Content-Length: ' . filesize($finalZip)); header('Content-Length: ' . filesize($finalZip));
header('Pragma: public'); header('Pragma: public');
header('Expires: 0'); header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');
// Push file
flush(); flush();
$fp = fopen($finalZip, 'rb'); $fp = fopen($finalZip, 'rb');
fpassthru($fp); fpassthru($fp);
fclose($fp); fclose($fp);
logAction("System", "Backup Download", "$session_name downloaded full backup."); // Log + UX
logAction("System", "Backup Download", ($session_name ?? 'Unknown User') . " downloaded full backup.");
flash_alert("Full backup downloaded."); flash_alert("Full backup downloaded.");
exit; exit;
} }
if (isset($_POST['backup_master_key'])) { if (isset($_POST['backup_master_key'])) {
validateCSRFToken($_POST['csrf_token']); validateCSRFToken($_POST['csrf_token']);

View File

@@ -6,7 +6,7 @@ if (isset($_POST['edit_mail_smtp_settings'])) {
validateCSRFToken($_POST['csrf_token']); validateCSRFToken($_POST['csrf_token']);
$config_smtp_provider = sanitizeInput($_POST['config_smtp_provider'] ?? 'standard_smtp'); $config_smtp_provider = sanitizeInput($_POST['config_smtp_provider']);
$config_smtp_host = sanitizeInput($_POST['config_smtp_host']); $config_smtp_host = sanitizeInput($_POST['config_smtp_host']);
$config_smtp_port = intval($_POST['config_smtp_port'] ?? 0); $config_smtp_port = intval($_POST['config_smtp_port'] ?? 0);
$config_smtp_encryption = sanitizeInput($_POST['config_smtp_encryption']); $config_smtp_encryption = sanitizeInput($_POST['config_smtp_encryption']);
@@ -22,7 +22,7 @@ if (isset($_POST['edit_mail_smtp_settings'])) {
mysqli_query($mysqli, " mysqli_query($mysqli, "
UPDATE settings SET UPDATE settings SET
config_smtp_provider = " . ($config_smtp_provider === 'none' ? "NULL" : "'$config_smtp_provider'") . ", config_smtp_provider = '$config_smtp_provider',
config_smtp_host = '$config_smtp_host', config_smtp_host = '$config_smtp_host',
config_smtp_port = $config_smtp_port, config_smtp_port = $config_smtp_port,
config_smtp_encryption = '$config_smtp_encryption', config_smtp_encryption = '$config_smtp_encryption',
@@ -48,7 +48,7 @@ if (isset($_POST['edit_mail_imap_settings'])) {
validateCSRFToken($_POST['csrf_token']); validateCSRFToken($_POST['csrf_token']);
$config_imap_provider = sanitizeInput($_POST['config_imap_provider'] ?? 'standard_imap'); $config_imap_provider = sanitizeInput($_POST['config_imap_provider']);
$config_imap_host = sanitizeInput($_POST['config_imap_host']); $config_imap_host = sanitizeInput($_POST['config_imap_host']);
$config_imap_port = intval($_POST['config_imap_port'] ?? 0); $config_imap_port = intval($_POST['config_imap_port'] ?? 0);
$config_imap_encryption = sanitizeInput($_POST['config_imap_encryption']); $config_imap_encryption = sanitizeInput($_POST['config_imap_encryption']);
@@ -64,7 +64,7 @@ if (isset($_POST['edit_mail_imap_settings'])) {
mysqli_query($mysqli, " mysqli_query($mysqli, "
UPDATE settings SET UPDATE settings SET
config_imap_provider = " . ($config_imap_provider === 'none' ? "NULL" : "'$config_imap_provider'") . ", config_imap_provider = '$config_imap_provider',
config_imap_host = '$config_imap_host', config_imap_host = '$config_imap_host',
config_imap_port = $config_imap_port, config_imap_port = $config_imap_port,
config_imap_encryption = '$config_imap_encryption', config_imap_encryption = '$config_imap_encryption',

View File

@@ -5,8 +5,8 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed"); defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
// Import shared code from user-side tickets/tasks as we reuse functions // Import shared code from user-side tickets/tasks as we reuse functions
require_once '../user/post/ticket.php'; require_once '../agent/post/ticket.php';
require_once '../user/post/task.php'; require_once '../agent/post/task.php';
if (isset($_POST['add_ticket_template'])) { if (isset($_POST['add_ticket_template'])) {

View File

@@ -5,7 +5,7 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed"); defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
// Import shared code from user-side vendor management as we reuse functions // Import shared code from user-side vendor management as we reuse functions
require_once '../user/post/vendor.php'; require_once '../agent/post/vendor.php';
if (isset($_POST['add_vendor_template'])) { if (isset($_POST['add_vendor_template'])) {

View File

@@ -18,10 +18,10 @@ require_once "includes/inc_all_admin.php";
<span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span>
</div> </div>
<select class="form-control" name="config_smtp_provider" id="config_smtp_provider"> <select class="form-control" name="config_smtp_provider" id="config_smtp_provider">
<option value="none" <?php if(($config_smtp_provider ?? '')==='none' || ($config_smtp_provider ?? '')==='') echo 'selected'; ?>>None (Disabled)</option> <option value="" <?php if(empty($config_smtp_provider)) { echo 'selected'; } ?>>None (Disabled)</option>
<option value="standard_smtp" <?php if(($config_smtp_provider ?? 'standard_smtp')==='standard_smtp') echo 'selected'; ?>>Standard SMTP (Username/Password)</option> <option value="standard_smtp" <?php if($config_smtp_provider === 'standard_smtp') { echo 'selected'; } ?>>Standard SMTP (Username/Password)</option>
<option value="google_oauth" <?php if(($config_smtp_provider ?? '')==='google_oauth') echo 'selected'; ?>>Google Workspace (OAuth)</option> <option value="google_oauth" <?php if($config_smtp_provider === 'google_oauth') { echo 'selected'; } ?>>Google Workspace (OAuth)</option>
<option value="microsoft_oauth" <?php if(($config_smtp_provider ?? '')==='microsoft_oauth') echo 'selected'; ?>>Microsoft 365 (OAuth)</option> <option value="microsoft_oauth" <?php if($config_smtp_provider === 'microsoft_oauth') { echo 'selected'; } ?>>Microsoft 365 (OAuth)</option>
</select> </select>
</div> </div>
<small class="text-secondary d-block mt-1" id="smtp_provider_hint"> <small class="text-secondary d-block mt-1" id="smtp_provider_hint">
@@ -116,10 +116,10 @@ require_once "includes/inc_all_admin.php";
<span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span>
</div> </div>
<select class="form-control" name="config_imap_provider" id="config_imap_provider"> <select class="form-control" name="config_imap_provider" id="config_imap_provider">
<option value="none" <?php if($config_imap_provider ==='') echo 'selected'; ?>>None (Disabled)</option> <option value="" <?php if(empty($config_imap_provider)) { echo 'selected'; } ?>>None (Disabled)</option>
<option value="standard_imap" <?php if(($config_imap_provider ?? 'standard_imap')==='standard_imap') echo 'selected'; ?>>Standard IMAP (Username/Password)</option> <option value="standard_imap" <?php if($config_imap_provider === 'standard_imap') { echo 'selected'; } ?>>Standard IMAP (Username/Password)</option>
<option value="google_oauth" <?php if(($config_imap_provider ?? '')==='google_oauth') echo 'selected'; ?>>Google Workspace (OAuth)</option> <option value="google_oauth" <?php if($config_imap_provider === 'google_oauth') { echo 'selected'; } ?>>Google Workspace (OAuth)</option>
<option value="microsoft_oauth" <?php if(($config_imap_provider ?? '')==='microsoft_oauth') echo 'selected'; ?>>Microsoft 365 (OAuth)</option> <option value="microsoft_oauth" <?php if($config_imap_provider === 'microsoft_oauth') { echo 'selected'; } ?>>Microsoft 365 (OAuth)</option>
</select> </select>
</div> </div>
<small class="text-secondary d-block mt-1" id="imap_provider_hint"> <small class="text-secondary d-block mt-1" id="imap_provider_hint">

View File

@@ -8,10 +8,15 @@ require_once "includes/inc_all_admin.php";
$sql = mysqli_query( $sql = mysqli_query(
$mysqli, $mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM ticket_templates "SELECT SQL_CALC_FOUND_ROWS *,
COUNT(task_template_id) AS task_count
FROM ticket_templates
LEFT JOIN task_templates ON task_template_ticket_template_id = ticket_template_id
WHERE (ticket_template_name LIKE '%$q%' OR ticket_template_description LIKE '%$q%') WHERE (ticket_template_name LIKE '%$q%' OR ticket_template_description LIKE '%$q%')
AND ticket_template_archived_at IS NULL AND ticket_template_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to" GROUP BY ticket_template_id
ORDER BY $sort $order
LIMIT $record_from, $record_to"
); );
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
@@ -46,14 +51,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<hr> <hr>
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover"> <table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if($num_rows[0] == 0){ echo "d-none"; } ?>"> <thead class="text-dark <?php if($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr> <tr>
<th> <th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_template_name&order=<?php echo $disp; ?>"> <a class="text-secondary" href="?<?= $url_query_strings_sort ?>&sort=ticket_template_name&order=<?= $disp ?>">
Template <?php if ($sort == 'ticket_template_name') { echo $order_icon; } ?> Template <?php if ($sort == 'ticket_template_name') { echo $order_icon; } ?>
</a> </a>
</th> </th>
<th>Tasks</th> <th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=task_count&order=<?php echo $disp; ?>">
Tasks <?php if ($sort == 'task_count') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th> <th class="text-center">Action</th>
</tr> </tr>
</thead> </thead>
@@ -66,6 +75,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']); $ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']); $ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']); $ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
$task_count = intval($row['task_count']);
?> ?>
<tr> <tr>
@@ -75,23 +85,23 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i> <i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body"> <div class="media-body">
<div> <div>
<a href="ticket_template_details.php?ticket_template_id=<?php echo $ticket_template_id; ?>"> <a href="ticket_template_details.php?ticket_template_id=<?= $ticket_template_id ?>">
<?php echo $ticket_template_name; ?> <?= $ticket_template_name ?>
</a> </a>
</div> </div>
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div> <div><small class="text-secondary"><?= $ticket_template_description ?></small></div>
</div> </div>
</div> </div>
</a> </a>
</td> </td>
<td>0</td> <td><?= $task_count ?></td>
<td> <td>
<div class="dropdown dropleft text-center"> <div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" data-toggle="dropdown"> <button class="btn btn-secondary btn-sm" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i> <i class="fas fa-ellipsis-h"></i>
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_template=<?php echo $ticket_template_id; ?>"> <a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_template=<?= $ticket_template_id ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete <i class="fas fa-fw fa-trash mr-2"></i>Delete
</a> </a>
</div> </div>
@@ -112,4 +122,3 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php <?php
require_once "modals/ticket_template/ticket_template_add.php"; require_once "modals/ticket_template/ticket_template_add.php";
require_once "../includes/footer.php"; require_once "../includes/footer.php";

View File

@@ -56,8 +56,6 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p> <p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
</div> </div>
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?no"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>TEST</h5></a>
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a> <a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
<a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a> <a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>

View File

@@ -675,3 +675,27 @@ if (isset($_POST['update_recurring_invoice_items_order'])) {
echo json_encode(['status' => 'success']); echo json_encode(['status' => 'success']);
exit; exit;
} }
if (isset($_GET['client_duplicate_check'])) {
enforceUserPermission('module_client', 2);
$name = sanitizeInput($_GET['name']);
$response['message'] = ""; // default
if (strlen($name) >= 5) {
$sql_clients = mysqli_query($mysqli, "SELECT client_name FROM clients
WHERE client_archived_at IS NULL
AND client_name LIKE '%$name%'
ORDER BY client_id DESC LIMIT 1"
);
if (mysqli_num_rows($sql_clients) > 0) {
while ($row = mysqli_fetch_array($sql_clients)) {
$response['message'] = "<i class='fas fa-fw fa-copy mr-2'></i> Potential duplicate: <i>" . nullable_htmlentities($row['client_name']) . "</i> already exists.";
}
}
}
echo json_encode($response);
}

View File

@@ -21,8 +21,14 @@ if (isset($_GET['asset_id'])) {
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1 LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
WHERE asset_id = $asset_id WHERE asset_id = $asset_id
$client_query $client_query
LIMIT 1
"); ");
if (mysqli_num_rows($sql) == 0) {
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='javascript:history.back()'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
} else {
$row = mysqli_fetch_array($sql); $row = mysqli_fetch_array($sql);
$client_id = intval($row['client_id']); $client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); $client_name = nullable_htmlentities($row['client_name']);
@@ -1001,7 +1007,7 @@ if (isset($_GET['asset_id'])) {
<?php <?php
if ($session_user_role == 3) { ?> if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?= $recurring_ticket_id; ?>"> <a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?= $recurring_ticket_id ?>&csrf_token=<?= $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete <i class="fas fa-fw fa-trash mr-2"></i>Delete
</a> </a>
</div> </div>
@@ -1177,7 +1183,7 @@ if (isset($_GET['asset_id'])) {
?> ?>
<script> <script>
function updateAssetNotes(asset_id) { function updateAssetNotes(asset_id) {
var notes = document.getElementById("assetNotes").value; var notes = document.getElementById("assetNotes").value;
@@ -1191,10 +1197,10 @@ if (isset($_GET['asset_id'])) {
} }
) )
} }
</script> </script>
<!-- JavaScript to Show/Hide Password Form Group --> <!-- JavaScript to Show/Hide Password Form Group -->
<script> <script>
$(document).ready(function() { $(document).ready(function() {
$('.authMethod').on('change', function() { $('.authMethod').on('change', function() {
var $form = $(this).closest('.authForm'); var $form = $(this).closest('.authForm');
@@ -1206,23 +1212,25 @@ if (isset($_GET['asset_id'])) {
}); });
$('.authMethod').trigger('change'); $('.authMethod').trigger('change');
}); });
</script> </script>
<!-- Include script to get TOTP code via the credential ID --> <!-- Include script to get TOTP code via the credential ID -->
<script src="js/credential_show_otp_via_id.js"></script> <script src="js/credential_show_otp_via_id.js"></script>
<script src="../js/bulk_actions.js"></script> <script src="../js/bulk_actions.js"></script>
<?php <?php
require_once "modals/asset/asset_interface_add.php"; require_once "modals/asset/asset_interface_add.php";
require_once "modals/asset/asset_interface_multiple_add.php"; require_once "modals/asset/asset_interface_multiple_add.php";
require_once "modals/asset/asset_interface_import.php"; require_once "modals/asset/asset_interface_import.php";
require_once "modals/asset/asset_interface_export.php"; require_once "modals/asset/asset_interface_export.php";
require_once "modals/ticket/ticket_add.php"; require_once "modals/ticket/ticket_add.php";
require_once "modals/recurring_ticket/recurring_ticket_add.php"; require_once "modals/recurring_ticket/recurring_ticket_add.php";
require_once "modals/credential/credential_add.php"; require_once "modals/credential/credential_add.php";
require_once "modals/document/document_add.php"; require_once "modals/document/document_add.php";
require_once "modals/file/file_upload.php"; require_once "modals/file/file_upload.php";
}
require_once "../includes/footer.php"; require_once "../includes/footer.php";

View File

@@ -37,17 +37,23 @@ enforceUserPermission('module_support');
//Asset Type from GET //Asset Type from GET
if (isset($_GET['type']) && ($_GET['type']) == 'workstation') { if (isset($_GET['type']) && ($_GET['type']) == 'workstation') {
$type_query = "asset_type = 'desktop' OR asset_type = 'laptop'"; $type_query = "asset_type = 'desktop' OR asset_type = 'laptop'";
$type_filter = "workstation";
} elseif (isset($_GET['type']) && ($_GET['type']) == 'server') { } elseif (isset($_GET['type']) && ($_GET['type']) == 'server') {
$type_query = "asset_type = 'server'"; $type_query = "asset_type = 'server'";
$type_filter = "server";
} elseif (isset($_GET['type']) && ($_GET['type']) == 'virtual') { } elseif (isset($_GET['type']) && ($_GET['type']) == 'virtual') {
$type_query = "asset_type = 'Virtual Machine'"; $type_query = "asset_type = 'Virtual Machine'";
$type_filter = "virtual";
} elseif (isset($_GET['type']) && ($_GET['type']) == 'network') { } elseif (isset($_GET['type']) && ($_GET['type']) == 'network') {
$type_query = "asset_type = 'Firewall/Router' OR asset_type = 'Switch' OR asset_type = 'Access Point'"; $type_query = "asset_type = 'Firewall/Router' OR asset_type = 'Switch' OR asset_type = 'Access Point'";
$type_filter = "network";
} elseif (isset($_GET['type']) && ($_GET['type']) == 'other') { } elseif (isset($_GET['type']) && ($_GET['type']) == 'other') {
$type_query = "asset_type NOT LIKE 'laptop' AND asset_type NOT LIKE 'desktop' AND asset_type NOT LIKE 'server' AND asset_type NOT LIKE 'virtual machine' AND asset_type NOT LIKE 'firewall/router' AND asset_type NOT LIKE 'switch' AND asset_type NOT LIKE 'access point'"; $type_query = "asset_type NOT LIKE 'laptop' AND asset_type NOT LIKE 'desktop' AND asset_type NOT LIKE 'server' AND asset_type NOT LIKE 'virtual machine' AND asset_type NOT LIKE 'firewall/router' AND asset_type NOT LIKE 'switch' AND asset_type NOT LIKE 'access point'";
$type_filter = "other";
} else { } else {
$type_query = "asset_type LIKE '%'"; $type_query = "asset_type LIKE '%'";
$_GET['type'] = ''; $_GET['type'] = '';
$type_filter = '';
} }
if (!$client_url) { if (!$client_url) {
@@ -133,19 +139,6 @@ $sql = mysqli_query(
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
// OS typeahead suggestions
$os_sql = mysqli_query($mysqli, "SELECT DISTINCT asset_os AS label FROM assets WHERE asset_archived_at IS NULL");
if ($os_sql && mysqli_num_rows($os_sql) > 0) {
$os_arr = [];
while ($row = mysqli_fetch_assoc($os_sql)) {
// jQuery UI Autocomplete expects {label: "...", value: "..."}
$label = $row['label'];
$os_arr[] = ['label' => $label, 'value' => $label];
}
$json_os = json_encode($os_arr);
}
?> ?>
<div class="col-sm-12 mb-3"> <div class="col-sm-12 mb-3">
@@ -185,8 +178,8 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
<div class="card-tools"> <div class="card-tools">
<?php if (lookupUserPermission("module_support") >= 2) { ?> <?php if (lookupUserPermission("module_support") >= 2) { ?>
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAssetModal"> <button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/asset/asset_add.php?<?= $client_url ?>&type=<?= $type_filter ?>">
<i class="fas fa-plus mr-2"></i>New <?php if (!empty($_GET['type'])) { echo ucwords(strip_tags(nullable_htmlentities($_GET['type']))); } else { echo "Asset"; } ?> <i class="fas fa-plus mr-2"></i>New <?php if ($type_filter) { echo ucwords($type_filter); } else { echo "Asset"; } ?>
</button> </button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu"> <div class="dropdown-menu">
@@ -716,24 +709,7 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
<script src="../js/bulk_actions.js"></script> <script src="../js/bulk_actions.js"></script>
<!-- JSON Autocomplete / type ahead -->
<link rel="stylesheet" href="../plugins/jquery-ui/jquery-ui.min.css">
<script src="../plugins/jquery-ui/jquery-ui.min.js"></script>
<script>
$(function() {
var operatingSystems = <?php echo $json_os; ?>;
$("#os").autocomplete({
source: operatingSystems, // Should be an array of objects with 'label' and 'value'
select: function(event, ui) {
$("#os").val(ui.item.label); // Set the input field value to the selected label
return false;
}
});
});
</script>
<?php <?php
require_once "modals/asset/asset_add.php";
require_once "modals/asset/asset_export.php"; require_once "modals/asset/asset_export.php";
if ($client_url) { if ($client_url) {
require_once "modals/asset/asset_import.php"; require_once "modals/asset/asset_import.php";

View File

@@ -1,113 +0,0 @@
<?php
require_once "includes/inc_all.php";
// Perms
enforceUserPermission('module_financial');
// Fetch categories
$query = "SELECT category_id, category_name FROM categories WHERE category_type ='Expense' AND category_archived_at IS NULL";
$result = mysqli_query($mysqli, $query);
$categories = [];
while($row = mysqli_fetch_assoc($result)) {
$categories[] = $row;
}
// Fetch years with budget
$query = "SELECT DISTINCT budget_year FROM budget ORDER BY budget_year ASC";
$result = mysqli_query($mysqli, $query);
$years = [];
while ($row = mysqli_fetch_assoc($result)) {
$years[] = $row['budget_year'];
}
// Fetch current year budgets
$currentYear = date("Y");
if (isset($_GET['year'])) {
$currentYear = intval($_GET['year']);
}
$query = "SELECT * FROM budget WHERE budget_year = $currentYear";
$result = mysqli_query($mysqli, $query);
$budgets = [];
while ($row = mysqli_fetch_assoc($result)) {
$budgets[] = $row;
}
$months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
$columnTotals = array_fill(0, 12, 0);
$grandTotal = 0;
?>
<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>Budget for <span id="currentYear"><?php echo $currentYear; ?></span></h3>
<div class="card-tools">
<a href="budget_edit.php" class="btn btn-primary">
<i class="fas fa-edit mr-2"></i>Edit Budget
</a>
</div>
</div>
<div class="card-body">
<form id="yearForm" method="GET" action="budget.php">
<div class="form-group">
<select class="form-control" name="year" id="yearSelect" onchange="submit();">
<?php foreach ($years as $year): ?>
<option value="<?php echo $year; ?>" <?php if ($year == $currentYear) { echo 'selected'; } ?>><?php echo $year; ?></option>
<?php endforeach; ?>
</select>
</div>
</form>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Expense</th>
<?php foreach ($months as $month): ?>
<th><?php echo $month; ?></th>
<?php endforeach; ?>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($categories as $category): ?>
<tr>
<td><?php echo nullable_htmlentities($category['category_name']); ?></td>
<?php
$rowTotal = 0;
foreach ($months as $index => $month):
$amount = getBudgetAmount($budgets, $category['category_id'], $index + 1);
$rowTotal += $amount;
$columnTotals[$index] += $amount;
?>
<td><?php echo $amount; ?></td>
<?php endforeach; ?>
<td><?php echo $rowTotal; ?></td>
</tr>
<?php
$grandTotal += $rowTotal;
endforeach; ?>
</tbody>
<tfoot>
<tr>
<th>Total</th>
<?php foreach ($columnTotals as $total): ?>
<th><?php echo $total; ?></th>
<?php endforeach; ?>
<th><?php echo $grandTotal; ?></th>
</tr>
</tfoot>
</table>
</div>
<?php
function getBudgetAmount($budgets, $categoryId, $month) {
foreach ($budgets as $budget) {
if ($budget['budget_category_id'] == $categoryId && $budget['budget_month'] == $month) {
return intval($budget['budget_amount']);
}
}
return 0;
}
require_once "../includes/footer.php";
?>

View File

@@ -1,114 +0,0 @@
<?php
require_once "includes/inc_all.php";
enforceUserPermission('module_financial', 2);
// Fetch categories
$query = "SELECT category_id, category_name FROM categories WHERE category_type ='Expense' AND category_archived_at IS NULL";
$result = mysqli_query($mysqli, $query);
$categories = [];
while($row = mysqli_fetch_assoc($result)) {
$categories[] = $row;
}
// Fetch current year budgets
$currentYear = date("Y");
if(isset($_GET['year'])) {
$currentYear = intval($_GET['year']);
}
$query = "SELECT * FROM budget WHERE budget_year = $currentYear";
$result = mysqli_query($mysqli, $query);
$budgets = [];
while($row = mysqli_fetch_assoc($result)) {
$budgets[] = $row;
}
$months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
$columnTotals = array_fill(0, 12, 0);
$grandTotal = 0;
?>
<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>Editing Budget for <span id="currentYear"><?php echo $currentYear; ?></span></h3>
<div class="card-tools">
<a href="budget.php" class="btn btn-default text-dark">
<i class="fas fa-eye mr-2"></i>View Budget
</a>
<button type="submit" name="save_budget" form="budgetForm" class="btn btn-primary"><i class="fas fa-fw fa-check mr-2"></i>Save Budget</button>
<button type="submit" name="delete_budget" form="budgetForm" class="btn btn-danger"><i class="fas fa-fw fa-trash mr-2"></i>Delete Budget</button>
</div>
</div>
<div class="card-body">
<form id="yearForm" method="GET" action="budget.php">
<div class="form-group">
<select class="form-control" name="year" id="yearSelect" onchange="submit();">
<?php for ($i = $currentYear - 10; $i <= $currentYear + 5; $i++): ?>
<option value="<?php echo $i; ?>" <?php if ($i == $currentYear) echo 'selected'; ?>><?php echo $i; ?></option>
<?php endfor; ?>
</select>
</div>
</form>
<form id="budgetForm" method="POST" action="post.php">
<input type="hidden" name="year" value="<?php echo $currentYear; ?>">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Expense</th>
<?php foreach ($months as $month): ?>
<th><?php echo $month; ?></th>
<?php endforeach; ?>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($categories as $category): ?>
<tr>
<td><?php echo nullable_htmlentities($category['category_name']); ?></td>
<?php
$rowTotal = 0;
foreach ($months as $index => $month):
$amount = getBudgetAmount($budgets, $category['category_id'], $index + 1);
$rowTotal += $amount;
$columnTotals[$index] += $amount;
?>
<td><input type='text' inputmode='numeric' pattern='[0-9]*' class="form-control" name="budget[<?php echo intval($category['category_id']); ?>][<?php echo $index + 1; ?>]" value="<?php echo $amount; ?>"></td>
<?php endforeach; ?>
<td><?php echo $rowTotal; ?></td>
</tr>
<?php
$grandTotal += $rowTotal;
endforeach; ?>
</tbody>
<tfoot>
<tr>
<th>Total</th>
<?php foreach ($columnTotals as $total): ?>
<th><?php echo $total; ?></th>
<?php endforeach; ?>
<th><?php echo $grandTotal; ?></th>
</tr>
</tfoot>
</table>
</form>
</div>
</div>
<?php
function getBudgetAmount($budgets, $categoryId, $month) {
foreach ($budgets as $budget) {
if ($budget['budget_category_id'] == $categoryId && $budget['budget_month'] == $month) {
return intval($budget['budget_amount']);
}
}
return 0;
}
require_once "../includes/footer.php";
?>

View File

@@ -86,7 +86,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="card-tools"> <div class="card-tools">
<?php if (lookupUserPermission("module_client") >= 2) { ?> <?php if (lookupUserPermission("module_client") >= 2) { ?>
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addClientModal"> <button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/client/client_add.php<?php if ($leads_filter) { echo "?lead=1"; } ?>">
<i class="fas fa-plus mr-2"></i>New <i class="fas fa-plus mr-2"></i>New
<?php if ($leads_filter == 0) { echo "Client"; } else { echo "Lead"; } ?> <?php if ($leads_filter == 0) { echo "Client"; } else { echo "Lead"; } ?>
</button> </button>
@@ -137,6 +137,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<i class="fas fa-fw fa-layer-group"></i><span class="d-none d-sm-inline ml-2">Action</span> (<span id="selectedCount">0</span>) <i class="fas fa-fw fa-layer-group"></i><span class="d-none d-sm-inline ml-2">Action</span> (<span id="selectedCount">0</span>)
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAddTicketModal">
<i class="fas fa-fw fa-life-ring mr-2"></i>Open Tickets
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditHourlyRateModal"> <a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditHourlyRateModal">
<i class="fas fa-fw fa-clock mr-2"></i>Set Hourly Rate <i class="fas fa-fw fa-clock mr-2"></i>Set Hourly Rate
</a> </a>
@@ -178,49 +182,27 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div <div
class="collapse class="collapse
<?php <?php
if ( if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01'
isset($_GET['dtf'])
|| $industry_filter || $industry_filter
|| $referral_filter || $referral_filter
|| (isset($_GET['tags']) && is_array($_GET['tags'])) || (isset($_GET['tags']) && is_array($_GET['tags']))
|| $_GET['canned_date'] !== "custom" ) )
{ { echo "show"; }
echo "show";
}
?> ?>
" "
id="advancedFilter" id="advancedFilter"
> >
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div> </div>
</div> </div>
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group">
<label>Date from</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date to</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group"> <div class="form-group">
<label>Tag</label> <label>Tag</label>
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple> <select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
@@ -623,6 +605,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
require_once "modals/client/client_bulk_edit_referral.php"; require_once "modals/client/client_bulk_edit_referral.php";
require_once "modals/client/client_bulk_edit_hourly_rate.php"; require_once "modals/client/client_bulk_edit_hourly_rate.php";
require_once "modals/client/client_bulk_assign_tags.php"; require_once "modals/client/client_bulk_assign_tags.php";
require_once "modals/client/client_bulk_add_ticket.php";
require_once "modals/client/client_bulk_email.php"; require_once "modals/client/client_bulk_email.php";
?> ?>
</form> </form>
@@ -634,7 +617,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<script src="../js/bulk_actions.js"></script> <script src="../js/bulk_actions.js"></script>
<?php <?php
require_once "modals/client/client_add.php";
require_once "modals/client/client_import.php"; require_once "modals/client/client_import.php";
require_once "modals/client/client_export.php"; require_once "modals/client/client_export.php";
require_once "../includes/footer.php"; require_once "../includes/footer.php";

View File

@@ -263,7 +263,7 @@ if (isset($_GET['contact_id'])) {
<i class="fa fa-fw fa-recycle mr-2"></i>New Recurring Ticket <i class="fa fa-fw fa-recycle mr-2"></i>New Recurring Ticket
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addAssetModal"> <a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/asset/asset_add.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>">
<i class="fa fa-fw fa-desktop mr-2"></i>New Asset <i class="fa fa-fw fa-desktop mr-2"></i>New Asset
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
@@ -1175,7 +1175,6 @@ if (isset($_GET['contact_id'])) {
require_once "modals/ticket/ticket_add.php"; require_once "modals/ticket/ticket_add.php";
require_once "modals/recurring_ticket/recurring_ticket_add.php"; require_once "modals/recurring_ticket/recurring_ticket_add.php";
require_once "modals/asset/asset_add.php";
require_once "modals/credential/credential_add.php"; require_once "modals/credential/credential_add.php";
require_once "modals/document/document_add.php"; require_once "modals/document/document_add.php";
require_once "modals/file/file_upload.php"; require_once "modals/file/file_upload.php";

View File

@@ -90,7 +90,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<h3 class="card-title mt-2"><i class="fa fa-fw fa-address-book mr-2"></i>Contacts</h3> <h3 class="card-title mt-2"><i class="fa fa-fw fa-address-book mr-2"></i>Contacts</h3>
<div class="card-tools"> <div class="card-tools">
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addContactModal"> <button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/contact/contact_add.php?client_id=<?= $client_id ?>">
<i class="fas fa-plus mr-2"></i>New Contact <i class="fas fa-plus mr-2"></i>New Contact
</button> </button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button> <button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
@@ -557,48 +557,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
<!-- JavaScript to Show/Hide Password Form Group -->
<script>
function generatePassword(type, id) {
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
jQuery.get(
"ajax.php", {
get_readable_pass: 'true'
},
function(data) {
//If we get a response from post.php, parse it as JSON
const password = JSON.parse(data);
// Set the password value to the correct modal, based on the type
if (type == "add") {
document.getElementById("password-add").value = password;
} else if (type == "edit") {
document.getElementById("password-edit-"+id.toString()).value = password;
}
}
);
}
$(document).ready(function() {
$('.authMethod').on('change', function() {
var $form = $(this).closest('.authForm');
if ($(this).val() === 'local') {
$form.find('.passwordGroup').show();
} else {
$form.find('.passwordGroup').hide();
}
});
$('.authMethod').trigger('change');
});
</script>
<script src="../js/bulk_actions.js"></script> <script src="../js/bulk_actions.js"></script>
<?php <?php
require_once "modals/contact/contact_add.php";
require_once "modals/contact/contact_export.php"; require_once "modals/contact/contact_export.php";
if ($client_url) { if ($client_url) {
require_once "modals/contact/contact_invite.php"; require_once "modals/contact/contact_invite.php";

View File

@@ -660,7 +660,7 @@ if ($user_config_dashboard_technical_enable == 1) {
<a class="small-box bg-warning" href="domains.php?sort=domain_expire&order=ASC"> <a class="small-box bg-warning" href="domains.php?sort=domain_expire&order=ASC">
<div class="inner"> <div class="inner">
<h3><?php echo $expiring_domains; ?></h3> <h3><?php echo $expiring_domains; ?></h3>
<p>Expiring Domains</p> <p>Expiring Domains <small>30 Day</small></p>
</div> </div>
<div class="icon"> <div class="icon">
<i class="fa fa-globe"></i> <i class="fa fa-globe"></i>
@@ -673,7 +673,7 @@ if ($user_config_dashboard_technical_enable == 1) {
<a class="small-box bg-primary" href="certificates.php?sort=certificate_expire&order=ASC"> <a class="small-box bg-primary" href="certificates.php?sort=certificate_expire&order=ASC">
<div class="inner"> <div class="inner">
<h3><?php echo $expiring_certificates; ?></h3> <h3><?php echo $expiring_certificates; ?></h3>
<p>Expiring Certificates</p> <p>Expiring Certificates<small>30 Day</small></p>
</div> </div>
<div class="icon"> <div class="icon">
<i class="fa fa-lock"></i> <i class="fa fa-lock"></i>

View File

@@ -163,17 +163,19 @@ $page_title = $row['document_name'];
<div class="col-md-3 d-print-none"> <div class="col-md-3 d-print-none">
<div class="row"> <div class="row">
<div class="col-12 mb-3"> <div class="col-12 mb-3">
<button type="button" class="btn btn-primary ajax-modal mr-2" <button type="button" class="btn btn-primary ajax-modal mr-1"
data-modal-size="lg" data-modal-size="lg"
data-modal-url="modals/document/document_edit.php?id=<?= $document_id ?>"> data-modal-url="modals/document/document_edit.php?id=<?= $document_id ?>">
<i class="fas fa-fw fa-edit"></i> <i class="fas fa-fw fa-edit" title="Edit"></i>
</button> </button>
<button type="button" class="btn btn-secondary mr-2" data-toggle="modal" data-target="#shareModal" <button type="button" class="btn btn-secondary mr-1" data-toggle="modal" data-target="#shareModal"
onclick="populateShareModal(<?php echo "$client_id, 'Document', $document_id"; ?>)"> onclick="populateShareModal(<?php echo "$client_id, 'Document', $document_id"; ?>)">
<i class="fas fa-fw fa-share"></i> <i class="fas fa-fw fa-share" title="Share"></i>
</button> </button>
<a class="btn btn-success mr-2" href="post.php?export_document=<?php echo $document_id; ?>"><i class='fas fa-fw fa-file-pdf'></i></a> <a class="btn btn-success mr-1" href="post.php?export_document=<?php echo $document_id; ?>"><i class='fas fa-fw fa-file-pdf' title="PDF Export"></i></a>
<button type="button" class="btn btn-secondary" onclick="window.print();"><i class="fas fa-fw fa-print"></i></button> <button type="button" class="btn btn-secondary mr-4" onclick="window.print();"><i class="fas fa-fw fa-print" title="Print"></i></button>
<a class="btn btn-warning mr-1 confirm-link" href="post.php?archive_document=<?= $document_id ?>" title="Archive"><i class='fas fa-fw fa-archive'></i></a>
<a class="btn btn-danger confirm-link" href="post.php?delete_document=<?= $document_id ?>&from=document_details" title="Delete"><i class='fas fa-fw fa-trash-alt'></i></a>
</div> </div>
</div> </div>
<div class="card card-body bg-light"> <div class="card card-body bg-light">

View File

@@ -117,34 +117,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (isset($_GET['dtf']) || $_GET['canned_date'] !== "custom" || $account_filter || $vendor_filter || $category_filter) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01' || $account_filter || $vendor_filter || $category_filter) { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">

View File

@@ -85,6 +85,8 @@ if (isset($_GET['query'])) {
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
WHERE ticket_archived_at IS NULL WHERE ticket_archived_at IS NULL
AND (ticket_subject LIKE '%$query%' AND (ticket_subject LIKE '%$query%'
OR ticket_details LIKE '%$query%'
OR CONCAT(ticket_prefix,ticket_number) LIKE '%$query%'
OR ticket_number = '$ticket_num_query') OR ticket_number = '$ticket_num_query')
$access_permission_query $access_permission_query
ORDER BY ticket_id DESC LIMIT 5" ORDER BY ticket_id DESC LIMIT 5"

View File

@@ -1,7 +1,7 @@
<!-- Main Sidebar Container --> <!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-<?php if (isset($_GET['client_id'])) { echo "gray"; } else { echo nullable_htmlentities($config_theme); } ?> d-print-none"> <aside class="main-sidebar sidebar-dark-<?php if (isset($_GET['client_id'])) { echo "gray"; } else { echo nullable_htmlentities($config_theme); } ?> d-print-none">
<a class="brand-link pb-1 mt-1" href="clients.php"> <a class="brand-link pb-1 mt-1" href="/agent/clients.php">
<p class="h5"> <p class="h5">
<i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i> <i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
<span class="brand-text"> <span class="brand-text">
@@ -19,14 +19,14 @@
<ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false">
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<a href="client_overview.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "client_overview.php") { echo "active"; } ?>"> <a href="/agent/client_overview.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "client_overview.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-tachometer-alt"></i> <i class="nav-icon fas fa-tachometer-alt"></i>
<p>Overview</p> <p>Overview</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="contacts.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "contacts.php" || basename($_SERVER["PHP_SELF"]) == "contact_details.php") { echo "active"; } ?>"> <a href="/agent/contacts.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "contacts.php" || basename($_SERVER["PHP_SELF"]) == "contact_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-address-book"></i> <i class="nav-icon fas fa-address-book"></i>
<p> <p>
Contacts Contacts
@@ -39,7 +39,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="locations.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "locations.php") { echo "active"; } ?>"> <a href="/agent/locations.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "locations.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-map-marker-alt"></i> <i class="nav-icon fas fa-map-marker-alt"></i>
<p> <p>
Locations Locations
@@ -55,7 +55,7 @@
<li class="nav-header mt-3">SUPPORT</li> <li class="nav-header mt-3">SUPPORT</li>
<li class="nav-item"> <li class="nav-item">
<a href="tickets.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets.php" || basename($_SERVER["PHP_SELF"]) == "ticket.php") { echo "active"; } ?>"> <a href="/agent/tickets.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets.php" || basename($_SERVER["PHP_SELF"]) == "ticket.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-life-ring"></i> <i class="nav-icon fas fa-life-ring"></i>
<p> <p>
Tickets Tickets
@@ -69,7 +69,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="recurring_tickets.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_tickets.php") { echo "active"; } ?>"> <a href="/agent/recurring_tickets.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_tickets.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-redo-alt"></i> <i class="nav-icon fas fa-redo-alt"></i>
<p> <p>
Recurring Tickets Recurring Tickets
@@ -83,7 +83,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="projects.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "projects.php" || basename($_SERVER["PHP_SELF"]) == "project_details.php") { echo "active"; } ?>"> <a href="/agent/projects.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "projects.php" || basename($_SERVER["PHP_SELF"]) == "project_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-project-diagram"></i> <i class="nav-icon fas fa-project-diagram"></i>
<p> <p>
Projects Projects
@@ -97,7 +97,7 @@
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="vendors.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "vendors.php") { echo "active"; } ?>"> <a href="/agent/vendors.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "vendors.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-building"></i> <i class="nav-icon fas fa-building"></i>
<p> <p>
Vendors Vendors
@@ -110,7 +110,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="calendar.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "calendar.php") { echo "active"; } ?>"> <a href="/agent/calendar.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "calendar.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-calendar-alt"></i> <i class="nav-icon fas fa-calendar-alt"></i>
<p> <p>
Calendar Calendar
@@ -128,7 +128,7 @@
<?php if (lookupUserPermission("module_support") >= 1) { ?> <?php if (lookupUserPermission("module_support") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="assets.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "assets.php" || basename($_SERVER["PHP_SELF"]) == "client_asset_details.php") { echo "active"; } ?>"> <a href="/agent/assets.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "assets.php" || basename($_SERVER["PHP_SELF"]) == "client_asset_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-desktop"></i> <i class="nav-icon fas fa-desktop"></i>
<p> <p>
Assets Assets
@@ -141,7 +141,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="software.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "software.php") { echo "active"; } ?>"> <a href="/agent/software.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "software.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-cube"></i> <i class="nav-icon fas fa-cube"></i>
<p> <p>
Licenses Licenses
@@ -155,7 +155,7 @@
<?php if (lookupUserPermission("module_credential") >= 1) { ?> <?php if (lookupUserPermission("module_credential") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="credentials.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "credentials.php") { echo "active"; } ?>"> <a href="/agent/credentials.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "credentials.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-key"></i> <i class="nav-icon fas fa-key"></i>
<p> <p>
Credentials Credentials
@@ -169,7 +169,7 @@
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="networks.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "networks.php") { echo "active"; } ?>"> <a href="/agent/networks.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "networks.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-network-wired"></i> <i class="nav-icon fas fa-network-wired"></i>
<p> <p>
Networks Networks
@@ -182,7 +182,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="racks.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "racks.php") { echo "active"; } ?>"> <a href="/agent/racks.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "racks.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-server"></i> <i class="nav-icon fas fa-server"></i>
<p> <p>
Racks Racks
@@ -195,7 +195,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="certificates.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "certificates.php") { echo "active"; } ?>"> <a href="/agent/certificates.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "certificates.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-lock"></i> <i class="nav-icon fas fa-lock"></i>
<p> <p>
Certificates Certificates
@@ -209,7 +209,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="domains.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "domains.php") { echo "active"; } ?>"> <a href="/agent/domains.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "domains.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-globe"></i> <i class="nav-icon fas fa-globe"></i>
<p> <p>
Domains Domains
@@ -223,7 +223,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="services.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "services.php") { echo "active"; } ?>"> <a href="/agent/services.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "services.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-stream"></i> <i class="nav-icon fas fa-stream"></i>
<p> <p>
Services Services
@@ -236,7 +236,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="documents.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "documents.php" || basename($_SERVER["PHP_SELF"]) == "document_details.php") { echo "active"; } ?>"> <a href="/agent/documents.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "documents.php" || basename($_SERVER["PHP_SELF"]) == "document_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-folder"></i> <i class="nav-icon fas fa-folder"></i>
<p> <p>
Documents Documents
@@ -252,7 +252,7 @@
<!-- Allow files even without module_support for things like contracts, etc. ) --> <!-- Allow files even without module_support for things like contracts, etc. ) -->
<li class="nav-item"> <li class="nav-item">
<a href="files.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "files.php") { echo "active"; } ?>"> <a href="/agent/files.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "files.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-paperclip"></i> <i class="nav-icon fas fa-paperclip"></i>
<p> <p>
Files Files
@@ -273,7 +273,7 @@
<?php if (lookupUserPermission("module_sales") >= 1) { ?> <?php if (lookupUserPermission("module_sales") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="invoices.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "invoices.php" || basename($_SERVER["PHP_SELF"]) == "invoice.php") { echo "active"; } ?>"> <a href="/agent/invoices.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "invoices.php" || basename($_SERVER["PHP_SELF"]) == "invoice.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-file-invoice"></i> <i class="nav-icon fas fa-file-invoice"></i>
<p> <p>
Invoices Invoices
@@ -286,7 +286,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="recurring_invoices.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_invoices.php" || basename($_SERVER["PHP_SELF"]) == "recurring_invoice.php") { echo "active"; } ?>"> <a href="/agent/recurring_invoices.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_invoices.php" || basename($_SERVER["PHP_SELF"]) == "recurring_invoice.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-redo-alt"></i> <i class="nav-icon fas fa-redo-alt"></i>
<p> <p>
Recurring Invoices Recurring Invoices
@@ -299,7 +299,7 @@
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="quotes.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "quotes.php" || basename($_SERVER["PHP_SELF"]) == "quote.php") { echo "active"; } ?>"> <a href="/agent/quotes.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "quotes.php" || basename($_SERVER["PHP_SELF"]) == "quote.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-comment-dollar"></i> <i class="nav-icon fas fa-comment-dollar"></i>
<p> <p>
Quotes Quotes
@@ -315,7 +315,7 @@
<?php if (lookupUserPermission("module_financial") >= 1) { ?> <?php if (lookupUserPermission("module_financial") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="payments.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "payments.php") { echo "active"; } ?>"> <a href="/agent/payments.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "payments.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-credit-card"></i> <i class="nav-icon fas fa-credit-card"></i>
<p> <p>
Payments Payments
@@ -329,7 +329,7 @@
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="trips.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "trips.php") { echo "active"; } ?>"> <a href="/agent/trips.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "trips.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-route"></i> <i class="nav-icon fas fa-route"></i>
<p> <p>
Trips Trips

View File

@@ -1,19 +1,19 @@
<?php <?php
// Configuration & core // Configuration & core
require_once "../config.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once "../functions.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once "../includes/check_login.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
// Page setup // Page setup
require_once "../includes/page_title.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
// Layout UI // Layout UI
require_once "../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once "../includes/top_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once "includes/get_side_nav_counts.php"; require_once 'includes/get_side_nav_counts.php';
require_once "includes/side_nav.php"; require_once 'includes/side_nav.php';
// Wrapper & alerts // Wrapper & alerts
require_once "../includes/inc_wrapper.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once "../includes/inc_alert_feedback.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once "../includes/filter_header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';

View File

@@ -1,9 +1,9 @@
<?php <?php
require_once "../config.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once "../functions.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once "../includes/check_login.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once "../includes/page_title.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
// Perms // Perms
enforceUserPermission('module_client'); enforceUserPermission('module_client');
@@ -35,7 +35,7 @@ if (isset($_GET['client_id'])) {
); );
if (mysqli_num_rows($sql) == 0) { if (mysqli_num_rows($sql) == 0) {
require_once "../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1></center>"; echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1></center>";
} else { } else {
@@ -304,10 +304,10 @@ if (isset($_GET['client_id'])) {
} }
} }
require_once "../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once "../includes/top_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once "includes/client_side_nav.php"; require_once 'includes/client_side_nav.php';
require_once "../includes/inc_wrapper.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once "../includes/inc_alert_feedback.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once "includes/inc_client_top_head.php"; require_once 'includes/inc_client_top_head.php';
require_once "../includes/filter_header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';

View File

@@ -1,12 +1,12 @@
<?php <?php
require_once "../config.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once "../functions.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once "../includes/check_login.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once "../includes/page_title.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
require_once "../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once "../includes/top_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once "includes/client_overview_side_nav.php"; require_once 'includes/client_overview_side_nav.php';
require_once "../includes/inc_wrapper.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once "../includes/inc_alert_feedback.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once "../includes/filter_header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';

View File

@@ -1,7 +1,7 @@
<!-- Main Sidebar Container --> <!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none"> <aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none">
<a class="brand-link" href="dashboard.php"> <a class="brand-link" href="/agent/dashboard.php">
<div class="brand-image"></div> <div class="brand-image"></div>
<span class="brand-text h4"><?php echo nullable_htmlentities($session_company_name); ?></span> <span class="brand-text h4"><?php echo nullable_htmlentities($session_company_name); ?></span>
</a> </a>
@@ -13,14 +13,14 @@
<nav> <nav>
<ul class="nav nav-pills nav-sidebar flex-column mt-3" data-widget="treeview" data-accordion="false"> <ul class="nav nav-pills nav-sidebar flex-column mt-3" data-widget="treeview" data-accordion="false">
<li class="nav-item"> <li class="nav-item">
<a href="dashboard.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "dashboard.php") { echo "active"; } ?>"> <a href="/agent/dashboard.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "dashboard.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-tachometer-alt"></i> <i class="nav-icon fas fa-tachometer-alt"></i>
<p>Dashboard</p> <p>Dashboard</p>
</a> </a>
</li> </li>
<?php if (lookupUserPermission("module_client") >= 1) { ?> <?php if (lookupUserPermission("module_client") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="clients.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "clients.php") { echo "active"; } ?>"> <a href="/agent/clients.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "clients.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-users"></i> <i class="nav-icon fas fa-users"></i>
<p> <p>
Clients Clients
@@ -36,7 +36,7 @@
<?php if ($config_module_enable_ticketing == 1) { ?> <?php if ($config_module_enable_ticketing == 1) { ?>
<li class="nav-header mt-3">SUPPORT</li> <li class="nav-header mt-3">SUPPORT</li>
<li class="nav-item"> <li class="nav-item">
<a href="tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets.php" || basename($_SERVER["PHP_SELF"]) == "ticket.php") { echo "active"; } ?>"> <a href="/agent/tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets.php" || basename($_SERVER["PHP_SELF"]) == "ticket.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-life-ring"></i> <i class="nav-icon fas fa-life-ring"></i>
<p> <p>
Tickets Tickets
@@ -47,7 +47,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="recurring_tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_tickets.php") { echo "active"; } ?>"> <a href="/agent/recurring_tickets.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_tickets.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-redo-alt"></i> <i class="nav-icon fas fa-redo-alt"></i>
<p> <p>
Recurring Tickets Recurring Tickets
@@ -58,7 +58,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="projects.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "projects.php" || basename($_SERVER["PHP_SELF"]) == "project_details.php") { echo "active"; } ?>"> <a href="/agent/projects.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "projects.php" || basename($_SERVER["PHP_SELF"]) == "project_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-project-diagram"></i> <i class="nav-icon fas fa-project-diagram"></i>
<p> <p>
Projects Projects
@@ -72,7 +72,7 @@
<?php } ?> <?php } ?>
<li class="nav-item"> <li class="nav-item">
<a href="calendar.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "calendar.php") { echo "active"; } ?>"> <a href="/agent/calendar.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "calendar.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-calendar-alt"></i> <i class="nav-icon fas fa-calendar-alt"></i>
<p>Calendar</p> <p>Calendar</p>
</a> </a>
@@ -80,7 +80,7 @@
<?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_sales") >= 1) { ?> <?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_sales") >= 1) { ?>
<li class="nav-header mt-3">BILLING</li> <li class="nav-header mt-3">BILLING</li>
<li class="nav-item"> <li class="nav-item">
<a href="quotes.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "quotes.php" || basename($_SERVER["PHP_SELF"]) == "quote.php") { echo "active"; } ?>"> <a href="/agent/quotes.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "quotes.php" || basename($_SERVER["PHP_SELF"]) == "quote.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-comment-dollar"></i> <i class="nav-icon fas fa-comment-dollar"></i>
<p> <p>
Quotes Quotes
@@ -91,7 +91,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "invoices.php" || basename($_SERVER["PHP_SELF"]) == "invoice.php") { echo "active"; } ?>"> <a href="/agent/invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "invoices.php" || basename($_SERVER["PHP_SELF"]) == "invoice.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-file-invoice"></i> <i class="nav-icon fas fa-file-invoice"></i>
<p> <p>
Invoices Invoices
@@ -102,7 +102,7 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="recurring_invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_invoices.php" || basename($_SERVER["PHP_SELF"]) == "recurring_invoice.php") { echo "active"; } ?>"> <a href="/agent/recurring_invoices.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_invoices.php" || basename($_SERVER["PHP_SELF"]) == "recurring_invoice.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-redo-alt"></i> <i class="nav-icon fas fa-redo-alt"></i>
<p> <p>
Recurring Invoices Recurring Invoices
@@ -113,13 +113,13 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="revenues.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "revenues.php") { echo "active"; } ?>"> <a href="/agent/revenues.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "revenues.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-hand-holding-usd"></i> <i class="nav-icon fas fa-hand-holding-usd"></i>
<p>Revenues</p> <p>Revenues</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="products.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "products.php") { echo "active"; } ?>"> <a href="/agent/products.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "products.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-box-open"></i> <i class="nav-icon fas fa-box-open"></i>
<p>Products</p> <p>Products</p>
</a> </a>
@@ -128,25 +128,25 @@
<?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_financial") >= 1) { ?> <?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_financial") >= 1) { ?>
<li class="nav-header mt-3">FINANCE</li> <li class="nav-header mt-3">FINANCE</li>
<li class="nav-item"> <li class="nav-item">
<a href="payments.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "payments.php") { echo "active"; } ?>"> <a href="/agent/payments.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "payments.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-credit-card"></i> <i class="nav-icon fas fa-credit-card"></i>
<p>Payments</p> <p>Payments</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="vendors.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "vendors.php") { echo "active"; } ?>"> <a href="/agent/vendors.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "vendors.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-building"></i> <i class="nav-icon fas fa-building"></i>
<p>Vendors</p> <p>Vendors</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expenses.php") { echo "active"; } ?>"> <a href="/agent/expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expenses.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-shopping-cart"></i> <i class="nav-icon fas fa-shopping-cart"></i>
<p>Expenses</p> <p>Expenses</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="recurring_expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_expenses.php") { echo "active"; } ?>"> <a href="/agent/recurring_expenses.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "recurring_expenses.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-redo-alt"></i> <i class="nav-icon fas fa-redo-alt"></i>
<p> <p>
Recurring Expenses Recurring Expenses
@@ -157,19 +157,19 @@
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="accounts.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "accounts.php") { echo "active"; } ?>"> <a href="/agent/accounts.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "accounts.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-piggy-bank"></i> <i class="nav-icon fas fa-piggy-bank"></i>
<p>Accounts</p> <p>Accounts</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="transfers.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "transfers.php") { echo "active"; } ?>"> <a href="/agent/transfers.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "transfers.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-exchange-alt"></i> <i class="nav-icon fas fa-exchange-alt"></i>
<p>Transfers</p> <p>Transfers</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="trips.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "trips.php") { echo "active"; } ?>"> <a href="/agent/trips.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "trips.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-route"></i> <i class="nav-icon fas fa-route"></i>
<p>Trips</p> <p>Trips</p>
</a> </a>
@@ -178,7 +178,7 @@
<?php if (lookupUserPermission("module_client") >= 1) { ?> <?php if (lookupUserPermission("module_client") >= 1) { ?>
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<a href="contacts.php" class="nav-link"> <a href="/agent/contacts.php" class="nav-link">
<i class="fas fa-users nav-icon"></i> <i class="fas fa-users nav-icon"></i>
<p>Client Overview</p> <p>Client Overview</p>
<i class="fas fa-angle-right nav-icon float-right"></i> <i class="fas fa-angle-right nav-icon float-right"></i>
@@ -188,7 +188,7 @@
<?php if (lookupUserPermission("module_reporting") >= 1) { ?> <?php if (lookupUserPermission("module_reporting") >= 1) { ?>
<li class="nav-item mt-3"> <li class="nav-item mt-3">
<a href="reports/" class="nav-link"> <a href="/agent/reports/" class="nav-link">
<i class="fas fa-chart-line nav-icon"></i> <i class="fas fa-chart-line nav-icon"></i>
<p>Reports</p> <p>Reports</p>
<i class="fas fa-angle-right nav-icon float-right"></i> <i class="fas fa-angle-right nav-icon float-right"></i>

View File

@@ -163,7 +163,9 @@ if (isset($_GET['invoice_id'])) {
//Product autocomplete //Product autocomplete
$products_sql = mysqli_query($mysqli, " $products_sql = mysqli_query($mysqli, "
SELECT SELECT
product_name AS label, CONCAT(product_code, ' - ', product_name) AS label,
product_name,
product_code,
product_type AS type, product_type AS type,
product_description AS description, product_description AS description,
product_price AS price, product_price AS price,
@@ -247,12 +249,12 @@ if (isset($_GET['invoice_id'])) {
<?php if ($invoice_status !== 'Paid' && $invoice_status !== 'Cancelled' && $invoice_status !== 'Draft' && $invoice_status !== 'Non-Billable' && $invoice_amount != 0) { ?> <?php if ($invoice_status !== 'Paid' && $invoice_status !== 'Cancelled' && $invoice_status !== 'Draft' && $invoice_status !== 'Non-Billable' && $invoice_amount != 0) { ?>
<div class="btn-group"> <div class="btn-group">
<button type="button" class="btn btn-success ajax-modal" data-modal-url="modals/invoice/invoice_pay.php?id=<?= $invoice_id ?>"><i class="fa fa-fw fa-credit-card mr-2"></i>Add Payment</button> <button type="button" class="btn btn-success ajax-modal" data-modal-url="modals/payment/payment_add.php?id=<?= $invoice_id ?>"><i class="fa fa-fw fa-credit-card mr-2"></i>Add Payment</button>
<?php if (mysqli_num_rows($sql_saved_payment_methods) > 0 && ($invoice_status === 'Sent' || $invoice_status === 'Viewed')) { ?> <?php if (mysqli_num_rows($sql_saved_payment_methods) > 0 && ($invoice_status === 'Sent' || $invoice_status === 'Viewed')) { ?>
<button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button> <button type="button" class="btn btn-success dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<a class="dropdown-item ajax-modal" href="#" data-modal-url="modals/invoice/invoice_saved_method_pay.php?id=<?= $invoice_id ?>"><i class="fas fa-fw fa-wallet mr-2"></i>Pay with Saved Card</a> <a class="dropdown-item ajax-modal" href="#" data-modal-url="modals/payment/payment_saved_method_add.php?id=<?= $invoice_id ?>"><i class="fas fa-fw fa-wallet mr-2"></i>Pay with Saved Card</a>
</div> </div>
<?php } ?> <?php } ?>
@@ -747,12 +749,20 @@ require_once "../includes/footer.php";
<script> <script>
$(function() { $(function() {
var availableProducts = <?php echo $json_products ?? '[]'?>; var availableProducts = <?php echo $json_products ?? '[]'?>;
$("#name").autocomplete({ $("#name").autocomplete({
source: availableProducts,
minLength: 1, minLength: 1,
delay: 0, delay: 0,
source: function(request, response) {
var term = $.ui.autocomplete.escapeRegex(request.term.toLowerCase());
var matcher = new RegExp(term, "i");
var matches = $.grep(availableProducts, function(item) {
return matcher.test(item.label) || matcher.test(item.product_name) || matcher.test(item.product_code);
});
response(matches);
},
select: function (event, ui) { select: function (event, ui) {
$("#name").val(ui.item.label); $("#name").val(ui.item.label);
$("#desc").val(ui.item.description); $("#desc").val(ui.item.description);

View File

@@ -97,6 +97,7 @@ $sql = mysqli_query(
"SELECT SQL_CALC_FOUND_ROWS * FROM invoices "SELECT SQL_CALC_FOUND_ROWS * FROM invoices
LEFT JOIN clients ON invoice_client_id = client_id LEFT JOIN clients ON invoice_client_id = client_id
LEFT JOIN categories ON invoice_category_id = category_id LEFT JOIN categories ON invoice_category_id = category_id
LEFT JOIN recurring_invoices ON invoice_recurring_invoice_id = recurring_invoice_id
WHERE ($status_query) WHERE ($status_query)
$overdue_query $overdue_query
$category_query $category_query
@@ -230,34 +231,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo $dtf; ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo $dtt; ?>">
</div> </div>
</div> </div>
</div> </div>
@@ -317,6 +299,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
Status <?php if ($sort == 'invoice_status') { echo $order_icon; } ?> Status <?php if ($sort == 'invoice_status') { echo $order_icon; } ?>
</a> </a>
</th> </th>
<th>Recurring</th>
<th class="text-center">Action</th> <th class="text-center">Action</th>
</tr> </tr>
</thead> </thead>
@@ -349,6 +332,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if ($client_net_terms == 0) { if ($client_net_terms == 0) {
$client_net_terms = $config_default_net_terms; $client_net_terms = $config_default_net_terms;
} }
$recurring_invoice_id = intval($row['recurring_invoice_id']);
$recurring_invoice_prefix = nullable_htmlentities($row['recurring_invoice_prefix']);
$recurring_invoice_number = nullable_htmlentities($row['recurring_invoice_number']);
if($recurring_invoice_id) {
$recurring_invoice_display = "<i class='fas fa-fw fa-redo-alt text-secondary mr-1'></i><a href='recurring_invoice.php?recurring_invoice_id=$recurring_invoice_id'>$recurring_invoice_prefix$recurring_invoice_number</a>";
} else {
$recurring_invoice_display = "-";
}
$now = time(); $now = time();
@@ -386,6 +379,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php echo $invoice_status; ?> <?php echo $invoice_status; ?>
</span> </span>
</td> </td>
<td><?= $recurring_invoice_display ?></td>
<td> <td>
<div class="dropdown dropleft text-center"> <div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown"> <button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -394,7 +388,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="dropdown-menu"> <div class="dropdown-menu">
<?php if ($invoice_status !== 'Paid' && $invoice_status !== 'Cancelled' && $invoice_status !== 'Draft' && $invoice_status !== 'Non-Billable' && $invoice_amount != 0) { ?> <?php if ($invoice_status !== 'Paid' && $invoice_status !== 'Cancelled' && $invoice_status !== 'Draft' && $invoice_status !== 'Non-Billable' && $invoice_amount != 0) { ?>
<a class="dropdown-item ajax-modal" href="#" <a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/invoice/invoice_pay.php?id=<?= $invoice_id ?>"> data-modal-url="modals/payment/payment_add.php?id=<?= $invoice_id ?>">
<i class="fa fa-fw fa-credit-card mr-2"></i>Add Payment <i class="fa fa-fw fa-credit-card mr-2"></i>Add Payment
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
@@ -454,6 +448,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php <?php
require_once "modals/invoice/invoice_add.php"; require_once "modals/invoice/invoice_add.php";
if ($client_url) { require_once "modals/invoice/invoice_payment_add_bulk.php"; } if ($client_url) { require_once "modals/payment/payment_bulk_add.php"; }
require_once "modals/invoice/invoice_export.php"; require_once "modals/invoice/invoice_export.php";
require_once "../includes/footer.php"; require_once "../includes/footer.php";

View File

@@ -23,6 +23,15 @@
} }
function displayTime() { function displayTime() {
// Show hrs, mins, sec input placeholders if auto-start is off
if (elapsedSecs === 0) {
document.getElementById("hours").value = "";
document.getElementById("minutes").value = "";
document.getElementById("seconds").value = "";
return;
}
let totalSeconds = elapsedSecs; let totalSeconds = elapsedSecs;
let hours = Math.floor(totalSeconds / 3600); let hours = Math.floor(totalSeconds / 3600);
totalSeconds %= 3600; totalSeconds %= 3600;

View File

@@ -1,15 +1,44 @@
<div class="modal" id="addAssetModal" tabindex="-1"> <?php
<div class="modal-dialog">
<div class="modal-content"> require_once '../../../includes/modal_header.php';
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-desktop mr-2"></i>New <?php if (!empty($_GET['type'])) { echo ucwords(strip_tags($_GET['type'])); }else{ echo "Asset"; } ?></h5> $client_id = intval($_GET['client_id'] ?? 0);
$contact_id = intval($_GET['contact_id'] ?? 0);
$type = nullable_htmlentities($_GET['type'] ?? '');
if ($client_id) {
$sql_network_select = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_archived_at IS NULL AND network_client_id = $client_id ORDER BY network_name ASC");
$sql_vendor_select = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id ORDER BY vendor_name ASC");
$sql_location_select = mysqli_query($mysqli, "SELECT location_id, location_name FROM locations WHERE location_archived_at IS NULL AND location_client_id = $client_id ORDER BY location_name ASC");
$sql_contact_select = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_archived_at IS NULL AND contact_client_id = $client_id ORDER BY contact_name ASC");
} else {
$sql_client_select = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
}
// OS typeahead suggestions
$os_sql = mysqli_query($mysqli, "SELECT DISTINCT asset_os AS label FROM assets WHERE asset_archived_at IS NULL");
if ($os_sql && mysqli_num_rows($os_sql) > 0) {
$os_arr = [];
while ($row = mysqli_fetch_assoc($os_sql)) {
// jQuery UI Autocomplete expects {label: "...", value: "..."}
$label = $row['label'];
$os_arr[] = ['label' => $label, 'value' => $label];
}
$json_os = json_encode($os_arr);
}
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-desktop mr-2"></i>New <?php if ($type) { echo ucwords($type); } else { echo "Asset"; } ?></h5>
<button type="button" class="close text-white" data-dismiss="modal"> <button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span> <span>&times;</span>
</button> </button>
</div> </div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off"> <form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>"> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<div class="modal-body ui-front"> <div class="modal-body ui-front">
@@ -40,8 +69,8 @@
<div class="tab-pane fade show active" id="pills-asset-details"> <div class="tab-pane fade show active" id="pills-asset-details">
<?php if ($client_url) { ?> <?php if ($client_id) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>"> <input type="hidden" name="client_id" value="<?= $client_id ?>">
<?php } else { ?> <?php } else { ?>
<div class="form-group"> <div class="form-group">
@@ -54,11 +83,10 @@
<option value="">- Select Client -</option> <option value="">- Select Client -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC"); while ($row = mysqli_fetch_array($sql_client_select)) {
while ($row = mysqli_fetch_array($sql)) { $client_id_select = intval($row['client_id']);
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); ?> $client_name = nullable_htmlentities($row['client_name']); ?>
<option <?php if ($client_id == isset($_GET['client'])) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option> <option <?php if ($client_id == $client_id_select) { echo "selected"; } ?> value="<?= $client_id_select ?>"><?= $client_name ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -96,14 +124,14 @@
<select class="form-control select2" name="type" required> <select class="form-control select2" name="type" required>
<option value="">- Select Type -</option> <option value="">- Select Type -</option>
<?php foreach($asset_types_array as $asset_type => $asset_icon) { ?> <?php foreach($asset_types_array as $asset_type => $asset_icon) { ?>
<option><?php echo $asset_type; ?></option> <option><?= $asset_type ?></option>
<?php } ?> <?php } ?>
</select> </select>
</div> </div>
</div> </div>
<?php //Do not display Make Model or Serial if Virtual is selected <?php //Do not display Make Model or Serial if Virtual is selected
if ($_GET['type'] !== 'virtual') { ?> if ($type !== 'virtual') { ?>
<div class="form-group"> <div class="form-group">
<label>Make</label> <label>Make</label>
<div class="input-group"> <div class="input-group">
@@ -135,7 +163,7 @@
</div> </div>
<?php } ?> <?php } ?>
<?php if ($_GET['type'] !== 'network' && $_GET['type'] !== 'other') { ?> <?php if ($type !== 'network' && $type !== 'other') { ?>
<div class="form-group"> <div class="form-group">
<label>Operating System</label> <label>Operating System</label>
<div class="input-group"> <div class="input-group">
@@ -150,7 +178,7 @@
</div> </div>
<div class="tab-pane fade" id="pills-asset-network"> <div class="tab-pane fade" id="pills-asset-network">
<?php if ($client_url) { ?> <?php if ($client_id) { ?>
<div class="form-group"> <div class="form-group">
<label>Network</label> <label>Network</label>
<div class="input-group"> <div class="input-group">
@@ -161,14 +189,13 @@
<option value="">- Select Network -</option> <option value="">- Select Network -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_archived_at IS NULL AND network_client_id = $client_id ORDER BY network_name ASC"); while ($row = mysqli_fetch_array($sql_network_select)) {
while ($row = mysqli_fetch_array($sql)) {
$network_id = intval($row['network_id']); $network_id = intval($row['network_id']);
$network_name = nullable_htmlentities($row['network_name']); $network_name = nullable_htmlentities($row['network_name']);
$network = nullable_htmlentities($row['network']); $network = nullable_htmlentities($row['network']);
?> ?>
<option value="<?php echo $network_id; ?>"><?php echo $network_name; ?> - <?php echo $network; ?></option> <option value="<?= $network_id ?>"><?= $network_name ?> - <?= $network ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -265,7 +292,7 @@
</div> </div>
</div> </div>
<?php if ($client_url) { ?> <?php if ($client_id) { ?>
<div class="form-group"> <div class="form-group">
<label>Location</label> <label>Location</label>
<div class="input-group"> <div class="input-group">
@@ -276,12 +303,11 @@
<option value="">- Select Location -</option> <option value="">- Select Location -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_archived_at IS NULL AND location_client_id = $client_id ORDER BY location_name ASC"); while ($row = mysqli_fetch_array($sql_location_select)) {
while ($row = mysqli_fetch_array($sql)) {
$location_id = intval($row['location_id']); $location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']); $location_name = nullable_htmlentities($row['location_name']);
?> ?>
<option value="<?php echo $location_id; ?>"><?php echo $location_name; ?></option> <option value="<?= $location_id ?>"><?= $location_name ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -298,16 +324,15 @@
<option value="">- Select Contact -</option> <option value="">- Select Contact -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_archived_at IS NULL AND contact_client_id = $client_id ORDER BY contact_name ASC"); while ($row = mysqli_fetch_array($sql_contact_select)) {
while ($row = mysqli_fetch_array($sql)) { $contact_id_select = intval($row['contact_id']);
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']); $contact_name = nullable_htmlentities($row['contact_name']);
?> ?>
<option <option
<?php if (isset($_GET['contact_id']) && $contact_id == intval($_GET['contact_id'])) { <?php if ($contact_id == $contact_id_select) {
echo "selected"; } echo "selected"; }
?> ?>
value="<?php echo $contact_id; ?>"><?php echo $contact_name; ?> value="<?= $contact_id_select ?>"><?= $contact_name ?>
</option> </option>
<?php } ?> <?php } ?>
@@ -336,7 +361,7 @@
<div class="tab-pane fade" id="pills-asset-purchase"> <div class="tab-pane fade" id="pills-asset-purchase">
<?php if ($client_url) { ?> <?php if ($client_id) { ?>
<div class="form-group"> <div class="form-group">
<label>Vendor</label> <label>Vendor</label>
<div class="input-group"> <div class="input-group">
@@ -347,8 +372,7 @@
<option value="">- Select Vendor -</option> <option value="">- Select Vendor -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id ORDER BY vendor_name ASC"); while ($row = mysqli_fetch_array($sql_vendor_select)) {
while ($row = mysqli_fetch_array($sql)) {
$vendor_id = intval($row['vendor_id']); $vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']); $vendor_name = nullable_htmlentities($row['vendor_name']);
?> ?>
@@ -360,7 +384,7 @@
</div> </div>
<?php } ?> <?php } ?>
<?php if ($_GET['type'] !== 'virtual') { ?> <?php if ($type !== 'virtual') { ?>
<div class="form-group"> <div class="form-group">
<label>Purchase Reference</label> <label>Purchase Reference</label>
<div class="input-group"> <div class="input-group">
@@ -392,7 +416,7 @@
</div> </div>
</div> </div>
<?php if ($_GET['type'] !== 'virtual') { ?> <?php if ($type !== 'virtual') { ?>
<div class="form-group"> <div class="form-group">
<label>Warranty Expire</label> <label>Warranty Expire</label>
<div class="input-group"> <div class="input-group">
@@ -449,7 +473,24 @@
<button type="submit" name="add_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button> <button type="submit" name="add_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button> <button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div> </div>
</form> </form>
</div>
</div> <!-- JSON Autocomplete / type ahead -->
</div> <link rel="stylesheet" href="/plugins/jquery-ui/jquery-ui.min.css">
<script src="/plugins/jquery-ui/jquery-ui.min.js"></script>
<script>
$(function() {
var operatingSystems = <?php echo $json_os; ?>;
$("#os").autocomplete({
source: operatingSystems, // Should be an array of objects with 'label' and 'value'
select: function(event, ui) {
$("#os").val(ui.item.label); // Set the input field value to the selected label
return false;
}
});
});
</script>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -21,7 +21,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" id="textInput" name="bulk_details"></textarea> <textarea class="form-control tinymceTicket" id="textInput" name="bulk_details"></textarea>
</div> </div>
<div class="row"> <div class="row">
@@ -52,7 +52,7 @@
<select class="form-control select2" name="bulk_category"> <select class="form-control select2" name="bulk_category">
<option value="0">- Not Categorized -</option> <option value="0">- Not Categorized -</option>
<?php <?php
$sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL"); $sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_categories)) { while ($row = mysqli_fetch_array($sql_categories)) {
$category_id = intval($row['category_id']); $category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']); $category_name = nullable_htmlentities($row['category_name']);
@@ -81,7 +81,7 @@
$sql = mysqli_query( $sql = mysqli_query(
$mysqli, $mysqli,
"SELECT user_id, user_name FROM users "SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC" WHERE user_type = 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
); );
while ($row = mysqli_fetch_array($sql)) { while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']); $user_id = intval($row['user_id']);

View File

@@ -53,37 +53,38 @@ $sql_asset_history = mysqli_query($mysqli, "SELECT * FROM asset_history
// Generate the HTML form content using output buffering. // Generate the HTML form content using output buffering.
ob_start(); ob_start();
?> ?>
<div class="modal-header bg-dark"> <div class="modal-header bg-dark">
<h5 class="modal-title"><i class='fa fa-fw fa-<?php echo $device_icon; ?> mr-2'></i>Editing asset: <strong><?php echo $asset_name; ?></strong></h5> <h5 class="modal-title"><i class='fa fa-fw fa-<?= $device_icon ?> mr-2'></i>Editing asset: <strong><?= $asset_name ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal"> <button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span> <span>&times;</span>
</button> </button>
</div> </div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off"> <form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>"> <input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>"> <input type="hidden" name="asset_id" value="<?= $asset_id ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>"> <input type="hidden" name="client_id" value="<?= $client_id ?>">
<div class="modal-body"> <div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3"> <ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details<?php echo $asset_id; ?>">Details</a> <a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-network<?php echo $asset_id; ?>">Network</a> <a class="nav-link" data-toggle="pill" href="#pills-network">Network</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-assignment<?php echo $asset_id; ?>">Assignment</a> <a class="nav-link" data-toggle="pill" href="#pills-assignment">Assignment</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-purchase<?php echo $asset_id; ?>">Purchase</a> <a class="nav-link" data-toggle="pill" href="#pills-purchase">Purchase</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes<?php echo $asset_id; ?>">Notes</a> <a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-history<?php echo $asset_id; ?>">History</a> <a class="nav-link" data-toggle="pill" href="#pills-history">History</a>
</li> </li>
</ul> </ul>
@@ -91,7 +92,7 @@ ob_start();
<div class="tab-content" <?php if (lookupUserPermission('module_support') <= 1) { echo 'inert'; } ?>> <div class="tab-content" <?php if (lookupUserPermission('module_support') <= 1) { echo 'inert'; } ?>>
<div class="tab-pane fade show active" id="pills-details<?php echo $asset_id; ?>"> <div class="tab-pane fade show active" id="pills-details">
<div class="form-group"> <div class="form-group">
<label>Name <strong class="text-danger">*</strong></label> <label>Name <strong class="text-danger">*</strong></label>
@@ -99,7 +100,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div> </div>
<input type="text" class="form-control" name="name" placeholder="Name the asset" maxlength="200" value="<?php echo $asset_name; ?>" required> <input type="text" class="form-control" name="name" placeholder="Name the asset" maxlength="200" value="<?= $asset_name ?>" required>
</div> </div>
</div> </div>
@@ -109,7 +110,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
</div> </div>
<input type="text" class="form-control" name="description" placeholder="Description of the asset" maxlength="255" value="<?php echo $asset_description; ?>"> <input type="text" class="form-control" name="description" placeholder="Description of the asset" maxlength="255" value="<?= $asset_description ?>">
</div> </div>
</div> </div>
@@ -135,7 +136,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div> </div>
<input type="text" class="form-control" name="make" placeholder="Manufacturer" maxlength="200" value="<?php echo $asset_make; ?>"> <input type="text" class="form-control" name="make" placeholder="Manufacturer" maxlength="200" value="<?= $asset_make ?>">
</div> </div>
</div> </div>
@@ -145,7 +146,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div> </div>
<input type="text" class="form-control" name="model" placeholder="Model Number" maxlength="200" value="<?php echo $asset_model; ?>"> <input type="text" class="form-control" name="model" placeholder="Model Number" maxlength="200" value="<?= $asset_model ?>">
</div> </div>
</div> </div>
@@ -155,7 +156,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-barcode"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-barcode"></i></span>
</div> </div>
<input type="text" class="form-control" name="serial" placeholder="Serial number" maxlength="200" value="<?php echo $asset_serial; ?>"> <input type="text" class="form-control" name="serial" placeholder="Serial number" maxlength="200" value="<?= $asset_serial ?>">
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
@@ -167,14 +168,14 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fab fa-fw fa-windows"></i></span> <span class="input-group-text"><i class="fab fa-fw fa-windows"></i></span>
</div> </div>
<input type="text" class="form-control" name="os" placeholder="ex Windows 10 Pro" maxlength="200" value="<?php echo $asset_os; ?>"> <input type="text" class="form-control" name="os" id="os" placeholder="ex Windows 10 Pro" maxlength="200" value="<?= $asset_os ?>">
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
</div> </div>
<div class="tab-pane fade" id="pills-network<?php echo $asset_id; ?>"> <div class="tab-pane fade" id="pills-network">
<div class="form-group"> <div class="form-group">
<label>Network</label> <label>Network</label>
@@ -227,7 +228,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-random"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-random"></i></span>
</div> </div>
<input type="text" class="form-control" name="nat_ip" value="<?php echo $asset_nat_ip; ?>" placeholder="10.52.4.55" data-inputmask="'alias': 'ip'" maxlength="200" data-mask> <input type="text" class="form-control" name="nat_ip" value="<?= $asset_nat_ip ?>" placeholder="10.52.4.55" data-inputmask="'alias': 'ip'" maxlength="200" data-mask>
</div> </div>
</div> </div>
@@ -237,7 +238,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-ethernet"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-ethernet"></i></span>
</div> </div>
<input type="text" class="form-control" name="ipv6" value="<?php echo $asset_ipv6; ?>" placeholder="ex. 2001:0db8:0000:0000:0000:ff00:0042:8329" maxlength="200"> <input type="text" class="form-control" name="ipv6" value="<?= $asset_ipv6 ?>" placeholder="ex. 2001:0db8:0000:0000:0000:ff00:0042:8329" maxlength="200">
</div> </div>
</div> </div>
@@ -247,7 +248,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-ethernet"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-ethernet"></i></span>
</div> </div>
<input type="text" class="form-control" name="mac" value="<?php echo $asset_mac; ?>" placeholder="MAC Address" data-inputmask="'alias': 'mac'" maxlength="200" data-mask> <input type="text" class="form-control" name="mac" value="<?= $asset_mac ?>" placeholder="MAC Address" data-inputmask="'alias': 'mac'" maxlength="200" data-mask>
</div> </div>
</div> </div>
@@ -257,7 +258,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-globe"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-globe"></i></span>
</div> </div>
<input type="text" class="form-control" name="uri" placeholder="URI http:// ftp:// ssh: etc" maxlength="500" value="<?php echo $asset_uri; ?>"> <input type="text" class="form-control" name="uri" placeholder="URI http:// ftp:// ssh: etc" maxlength="500" value="<?= $asset_uri ?>">
</div> </div>
</div> </div>
@@ -282,7 +283,7 @@ ob_start();
</div> </div>
<div class="tab-pane fade" id="pills-assignment<?php echo $asset_id; ?>"> <div class="tab-pane fade" id="pills-assignment">
<div class="form-group"> <div class="form-group">
<label>Physical Location</label> <label>Physical Location</label>
@@ -290,7 +291,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
</div> </div>
<input type="text" class="form-control" name="physical_location" placeholder="Physical location eg. Floor 2, Closet B" maxlength="200" value="<?php echo $asset_physical_location; ?>"> <input type="text" class="form-control" name="physical_location" placeholder="Physical location eg. Floor 2, Closet B" maxlength="200" value="<?= $asset_physical_location ?>">
</div> </div>
</div> </div>
@@ -315,7 +316,7 @@ ob_start();
$location_name_select_display = $location_name_select; $location_name_select_display = $location_name_select;
} }
?> ?>
<option <?php if ($asset_location_id == $location_id_select) { echo "selected"; } ?> value="<?php echo $location_id_select; ?>"><?php echo $location_name_select_display; ?></option> <option <?php if ($asset_location_id == $location_id_select) { echo "selected"; } ?> value="<?= $location_id_select ?>"><?= $location_name_select_display ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -343,8 +344,8 @@ ob_start();
$contact_name_select_display = $contact_name_select; $contact_name_select_display = $contact_name_select;
} }
?> ?>
<option <?php if ($asset_contact_id == $contact_id_select) { echo "selected"; } ?> value="<?php echo $contact_id_select; ?>"> <option <?php if ($asset_contact_id == $contact_id_select) { echo "selected"; } ?> value="<?= $contact_id_select ?>">
<?php echo $contact_name_select_display; ?> <?= $contact_name_select_display ?>
</option> </option>
<?php } ?> <?php } ?>
@@ -360,7 +361,7 @@ ob_start();
</div> </div>
<select class="form-control select2" name="status"> <select class="form-control select2" name="status">
<?php foreach($asset_status_array as $asset_status_select) { ?> <?php foreach($asset_status_array as $asset_status_select) { ?>
<option <?php if ($asset_status_select == $asset_status) { echo "selected"; } ?>><?php echo $asset_status_select; ?></option> <option <?php if ($asset_status_select == $asset_status) { echo "selected"; } ?>><?= $asset_status_select ?></option>
<?php } ?> <?php } ?>
</select> </select>
</div> </div>
@@ -368,7 +369,7 @@ ob_start();
</div> </div>
<div class="tab-pane fade" id="pills-purchase<?php echo $asset_id; ?>"> <div class="tab-pane fade" id="pills-purchase">
<div class="form-group"> <div class="form-group">
<label>Vendor</label> <label>Vendor</label>
@@ -391,7 +392,7 @@ ob_start();
$vendor_name_select_display = $vendor_name_select; $vendor_name_select_display = $vendor_name_select;
} }
?> ?>
<option <?php if ($asset_vendor_id == $vendor_id_select) { echo "selected"; } ?> value="<?php echo $vendor_id_select; ?>"><?php echo $vendor_name_select_display; ?></option> <option <?php if ($asset_vendor_id == $vendor_id_select) { echo "selected"; } ?> value="<?= $vendor_id_select ?>"><?= $vendor_name_select_display ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -405,7 +406,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
</div> </div>
<input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number" value="<?php echo $asset_purchase_reference; ?>"> <input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number" value="<?= $asset_purchase_reference ?>">
</div> </div>
</div> </div>
@@ -415,7 +416,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
</div> </div>
<input type="date" class="form-control" name="purchase_date" max="2999-12-31" value="<?php echo $asset_purchase_date; ?>"> <input type="date" class="form-control" name="purchase_date" max="2999-12-31" value="<?= $asset_purchase_date ?>">
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
@@ -426,7 +427,7 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar-check"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-calendar-check"></i></span>
</div> </div>
<input type="date" class="form-control" name="install_date" max="2999-12-31" value="<?php echo $asset_install_date; ?>"> <input type="date" class="form-control" name="install_date" max="2999-12-31" value="<?= $asset_install_date ?>">
</div> </div>
</div> </div>
@@ -437,18 +438,18 @@ ob_start();
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar-times"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-calendar-times"></i></span>
</div> </div>
<input type="date" class="form-control" name="warranty_expire" max="2999-12-31" value="<?php echo $asset_warranty_expire; ?>"> <input type="date" class="form-control" name="warranty_expire" max="2999-12-31" value="<?= $asset_warranty_expire ?>">
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
</div> </div>
<div class="tab-pane fade" id="pills-notes<?php echo $asset_id; ?>"> <div class="tab-pane fade" id="pills-notes">
<div class="mb-3 text-center"> <div class="mb-3 text-center">
<?php if ($asset_photo) { ?> <?php if ($asset_photo) { ?>
<img class="img-fluid" alt="asset_photo" src="<?php echo "../uploads/clients/$client_id/$asset_photo"; ?>"> <img class="img-fluid" alt="asset_photo" src="<?= "../uploads/clients/$client_id/$asset_photo" ?>">
<?php } ?> <?php } ?>
</div> </div>
@@ -458,7 +459,7 @@ ob_start();
</div> </div>
<div class="form-group"> <div class="form-group">
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"><?php echo $asset_notes; ?></textarea> <textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"><?= $asset_notes ?></textarea>
</div> </div>
<p class="text-muted text-right">Asset ID: <?= $asset_id ?></p> <p class="text-muted text-right">Asset ID: <?= $asset_id ?></p>
@@ -466,7 +467,7 @@ ob_start();
</div> </div>
<div class="tab-pane fade" id="pills-history<?php echo $asset_id; ?>"> <div class="tab-pane fade" id="pills-history">
<div class="form-group"> <div class="form-group">
<label>Asset History</label> <label>Asset History</label>

View File

@@ -14,7 +14,7 @@
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>"> <input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?> <?php } ?>
<div class="modal-body"> <div class="modal-body">
<p><strong>Format csv file with headings & data:</strong><br>Name, Description, Type, Make, Model, Serial, OS, Purchase Date, Assigned To, Location, Physical Location</p> <p><strong>Format csv file with headings & data:</strong><br>Name, Description, Type, Make, Model, Serial, OS, Purchase Date, Assigned To, Location, Physical Location, Notes</p>
<hr> <hr>
<div class="form-group my-4"> <div class="form-group my-4">
<input type="file" class="form-control-file" name="file" accept=".csv" required> <input type="file" class="form-control-file" name="file" accept=".csv" required>

View File

@@ -1,14 +1,27 @@
<div class="modal" id="addClientModal" tabindex="-1"> <?php
<div class="modal-dialog">
<div class="modal-content border-dark"> require_once '../../../includes/modal_header.php';
<div class="modal-header bg-dark">
// Filters
$leads_filter = intval($_GET['lead'] ?? 0);
// Selects
$referral_sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Referral' AND category_archived_at IS NULL ORDER BY category_name ASC");
$sql_tags_select = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 1 ORDER BY tag_name ASC");
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-user-plus mr-2"></i>Creating New <?php if($leads_filter == 0){ echo "Client"; } else { echo "Lead"; } ?></h5> <h5 class="modal-title"><i class="fa fa-fw fa-user-plus mr-2"></i>Creating New <?php if($leads_filter == 0){ echo "Client"; } else { echo "Lead"; } ?></h5>
<button type="button" class="close text-white" data-dismiss="modal"> <button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span> <span>&times;</span>
</button> </button>
</div> </div>
<ul class="modal-header nav nav-pills nav-justified"> <ul class="modal-header nav nav-pills nav-justified">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a> <a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a>
</li> </li>
@@ -26,9 +39,9 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a> <a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
</li> </li>
</ul> </ul>
<form action="post.php" method="post" autocomplete="off"> <form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>"> <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body"> <div class="modal-body">
@@ -42,13 +55,16 @@
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div> </div>
<input type="text" class="form-control" name="name" placeholder="Name or Company" maxlength="200" required autofocus> <input type="text" class="form-control" name="name" id="client_name" placeholder="Name or Company" maxlength="200" onfocusout="client_duplicate_check()" required autofocus>
<div class="input-group-append"> <div class="input-group-append">
<div class="input-group-text"> <div class="input-group-text">
<input type="checkbox" name="lead" value="1" <?php if($leads_filter == 1){ echo "checked"; } ?>> <input type="checkbox" name="lead" value="1" <?php if($leads_filter == 1){ echo "checked"; } ?>>
</div> </div>
</div> </div>
</div> </div>
<div class="mt-2">
<span class="text-info" id="client_duplicate_info"></span>
</div>
</div> </div>
<div class="form-group"> <div class="form-group">
@@ -81,7 +97,6 @@
<option value="">- Select Referral -</option> <option value="">- Select Referral -</option>
<?php <?php
$referral_sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Referral' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($referral_sql)) { while ($row = mysqli_fetch_array($referral_sql)) {
$referral = nullable_htmlentities($row['category_name']); ?> $referral = nullable_htmlentities($row['category_name']); ?>
<option><?php echo $referral; ?></option> <option><?php echo $referral; ?></option>
@@ -116,7 +131,6 @@
<select class="form-control select2" name="tags[]" data-placeholder="- Select Tags -"multiple> <select class="form-control select2" name="tags[]" data-placeholder="- Select Tags -"multiple>
<?php <?php
$sql_tags_select = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 1 ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_tags_select)) { while ($row = mysqli_fetch_array($sql_tags_select)) {
$tag_id_select = intval($row['tag_id']); $tag_id_select = intval($row['tag_id']);
$tag_name_select = nullable_htmlentities($row['tag_name']); $tag_name_select = nullable_htmlentities($row['tag_name']);
@@ -369,10 +383,7 @@
<button type="submit" name="add_client" class="btn btn-primary text-bold" onclick="promptPrimaryContact()"><i class="fa fa-check mr-2"></i>Create</button> <button type="submit" name="add_client" class="btn btn-primary text-bold" onclick="promptPrimaryContact()"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Close</button> <button type="button" class="btn btn-outline-secondary" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Close</button>
</div> </div>
</form> </form>
</div>
</div>
</div>
<script> <script>
// Checks/prompts that the primary contact field (required) is populated // Checks/prompts that the primary contact field (required) is populated
@@ -383,3 +394,23 @@
} }
} }
</script> </script>
<script>
// Checks for duplicate clients
function client_duplicate_check() {
var name = document.getElementById("client_name").value;
//Send a GET request to ajax.php as ajax.php?client_duplicate_check=true&name=NAME
jQuery.get(
"ajax.php",
{client_duplicate_check: 'true', name: name},
function(data) {
//If we get a response from ajax.php, parse it as JSON
const client_duplicate_data = JSON.parse(data);
document.getElementById("client_duplicate_info").innerHTML = client_duplicate_data.message;
}
);
}
</script>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -0,0 +1,137 @@
<div class="modal" id="bulkAddTicketModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-life-ring mr-2"></i>Creating Tickets for Clients</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Subject <strong class="text-danger">*</strong></label>
<input type="text" class="form-control" name="bulk_subject" placeholder="Enter a subject" maxlength="200">
</div>
<div class="form-group">
<textarea class="form-control tinymceTicket" id="textInput" name="bulk_details"></textarea>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label>Priority <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-thermometer-half"></i></span>
</div>
<select class="form-control select2" name="bulk_priority">
<option>Low</option>
<option>Medium</option>
<option>High</option>
</select>
</div>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Category</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-layer-group"></i></span>
</div>
<select class="form-control select2" name="bulk_category">
<option value="0">- Not Categorized -</option>
<?php
$sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL");
while ($row = mysqli_fetch_array($sql_categories)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
?>
<option value="<?php echo $category_id; ?>"><?php echo $category_name; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label>Assign to</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user-check"></i></span>
</div>
<select class="form-control select2" name="bulk_assigned_to">
<option value="0">Not Assigned</option>
<?php
$sql = mysqli_query(
$mysqli,
"SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
);
while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']);
$user_name = nullable_htmlentities($row['user_name']); ?>
<option value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Project</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-project-diagram"></i></span>
</div>
<select class="form-control select2" name="bulk_project">
<option value="0">- None -</option>
<?php
$sql_projects = mysqli_query($mysqli, "SELECT * FROM projects WHERE project_completed_at IS NULL AND project_archived_at IS NULL ORDER BY project_name ASC");
while ($row = mysqli_fetch_array($sql_projects)) {
$project_id_select = intval($row['project_id']);
$project_name_select = nullable_htmlentities($row['project_name']); ?>
<option value="<?php echo $project_id_select; ?>"><?php echo $project_name_select; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
</div>
<?php if ($config_module_enable_accounting) { ?>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="bulk_billable" <?php if ($config_ticket_default_billable == 1) { echo "checked"; } ?> value="1" id="billableSwitch">
<label class="custom-control-label" for="billableSwitch">Billable</label>
</div>
</div>
<?php } ?>
</div>
<div class="modal-footer">
<button type="submit" name="bulk_add_client_ticket" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</div>
</div>
</div>

View File

@@ -23,7 +23,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="submit" name="bulk_edit_client_hourly_rate" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Assign</button> <button type="submit" name="bulk_edit_client_hourly_rate" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button> <button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div> </div>
</div> </div>

View File

@@ -23,7 +23,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="submit" name="bulk_edit_client_industry" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Assign</button> <button type="submit" name="bulk_edit_client_industry" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button> <button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div> </div>
</div> </div>

View File

@@ -28,10 +28,8 @@
</select> </select>
<div class="input-group-append"> <div class="input-group-append">
<button class="btn btn-secondary" type="button" <button class="btn btn-secondary ajax-modal" type="button"
data-toggle="ajax-modal" data-modal-url="/admin/modals/category/category_add.php?category=Referral">
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Referral">
<i class="fas fa-fw fa-plus"></i> <i class="fas fa-fw fa-plus"></i>
</button> </button>
</div> </div>
@@ -41,7 +39,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="submit" name="bulk_edit_client_referral" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Assign</button> <button type="submit" name="bulk_edit_client_referral" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button> <button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div> </div>
</div> </div>

View File

@@ -1,27 +1,42 @@
<div class="modal" id="addContactModal" tabindex="-1"> <?php
<div class="modal-dialog">
<div class="modal-content"> require_once '../../../includes/modal_header.php';
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-user-plus mr-2"></i>New Contact</h5> $client_id = intval($_GET['client_id'] ?? 0);
if ($client_id) {
$sql_location_select = mysqli_query($mysqli, "SELECT location_id, location_name FROM locations WHERE location_archived_at IS NULL AND location_client_id = $client_id ORDER BY location_name ASC");
} else {
$sql_client_select = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
}
$sql_tags_select = mysqli_query($mysqli, "SELECT tag_id, tag_name FROM tags WHERE tag_type = 3 ORDER BY tag_name ASC");
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-plus mr-2"></i>New Contact</h5>
<button type="button" class="close text-white" data-dismiss="modal"> <button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span> <span>&times;</span>
</button> </button>
</div> </div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off"> <form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<div class="modal-body"> <div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3"> <ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details"><i class="fa fa-fw fa-user mr-2"></i>Details</a> <a class="nav-link active" data-toggle="pill" href="#pills-details"><i class="fas fa-fw fa-user mr-2"></i>Details</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-photo"><i class="fa fa-fw fa-image mr-2"></i>Photo</a> <a class="nav-link" data-toggle="pill" href="#pills-photo"><i class="fas fa-fw fa-image mr-2"></i>Photo</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-access"><i class="fa fa-fw fa-lock mr-2"></i>Access</a> <a class="nav-link" data-toggle="pill" href="#pills-access"><i class="fas fa-fw fa-lock mr-2"></i>Access</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes"><i class="fa fa-fw fa-edit mr-2"></i>Notes</a> <a class="nav-link" data-toggle="pill" href="#pills-notes"><i class="fas fa-fw fa-edit mr-2"></i>Notes</a>
</li> </li>
</ul> </ul>
@@ -31,8 +46,8 @@
<div class="tab-pane fade show active" id="pills-details"> <div class="tab-pane fade show active" id="pills-details">
<?php if ($client_url) { ?> <?php if ($client_id) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>"> <input type="hidden" name="client_id" value="<?= $client_id ?>">
<?php } else { ?> <?php } else { ?>
<div class="form-group"> <div class="form-group">
@@ -45,11 +60,10 @@
<option value="">- Select Client -</option> <option value="">- Select Client -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC"); while ($row = mysqli_fetch_array($sql_client_select)) {
while ($row = mysqli_fetch_array($sql)) { $client_id_select = intval($row['client_id']);
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); ?> $client_name = nullable_htmlentities($row['client_name']); ?>
<option <?php if ($client_id == isset($_GET['client'])) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option> <option <?php if ($client_id_select == $client_id) { echo "selected"; } ?> value="<?= $client_id_select ?>"><?= $client_name ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -138,7 +152,7 @@
</div> </div>
</div> </div>
<?php if($client_url) { ?> <?php if($client_id) { ?>
<div class="form-group"> <div class="form-group">
<label>Location</label> <label>Location</label>
<div class="input-group"> <div class="input-group">
@@ -149,12 +163,11 @@
<option value="">- Select Location -</option> <option value="">- Select Location -</option>
<?php <?php
$sql = mysqli_query($mysqli, "SELECT location_id, location_name FROM locations WHERE location_archived_at IS NULL AND location_client_id = $client_id ORDER BY location_name ASC"); while ($row = mysqli_fetch_array($sql_location_select)) {
while ($row = mysqli_fetch_array($sql)) {
$location_id = intval($row['location_id']); $location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']); $location_name = nullable_htmlentities($row['location_name']);
?> ?>
<option value="<?php echo $location_id; ?>"><?php echo $location_name; ?></option> <option value="<?= $location_id ?>"><?= $location_name ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -270,12 +283,11 @@
<select class="form-control select2" name="tags[]" data-placeholder="Add some tags" multiple> <select class="form-control select2" name="tags[]" data-placeholder="Add some tags" multiple>
<?php <?php
$sql_tags_select = mysqli_query($mysqli, "SELECT * FROM tags WHERE tag_type = 3 ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_tags_select)) { while ($row = mysqli_fetch_array($sql_tags_select)) {
$tag_id_select = intval($row['tag_id']); $tag_id = intval($row['tag_id']);
$tag_name_select = nullable_htmlentities($row['tag_name']); $tag_name = nullable_htmlentities($row['tag_name']);
?> ?>
<option value="<?php echo $tag_id_select; ?>"><?php echo $tag_name_select; ?></option> <option value="<?= $tag_id ?>"><?= $tag_name ?></option>
<?php } ?> <?php } ?>
</select> </select>
@@ -297,7 +309,44 @@
<button type="submit" name="add_contact" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button> <button type="submit" name="add_contact" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button> <button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div> </div>
</form> </form>
</div> <!-- JavaScript to Show/Hide Password Form Group -->
</div> <script>
</div>
function generatePassword(type, id) {
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
jQuery.get(
"ajax.php", {
get_readable_pass: 'true'
},
function(data) {
//If we get a response from post.php, parse it as JSON
const password = JSON.parse(data);
// Set the password value to the correct modal, based on the type
if (type == "add") {
document.getElementById("password-add").value = password;
} else if (type == "edit") {
document.getElementById("password-edit-"+id.toString()).value = password;
}
}
);
}
$(document).ready(function() {
$('.authMethod').on('change', function() {
var $form = $(this).closest('.authForm');
if ($(this).val() === 'local') {
$form.find('.passwordGroup').show();
} else {
$form.find('.passwordGroup').hide();
}
});
$('.authMethod').trigger('change');
});
</script>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -35,6 +35,18 @@ $contact_technical = intval($row['contact_technical']);
$contact_created_at = nullable_htmlentities($row['contact_created_at']); $contact_created_at = nullable_htmlentities($row['contact_created_at']);
$contact_location_id = intval($row['contact_location_id']); $contact_location_id = intval($row['contact_location_id']);
$location_name = nullable_htmlentities($row['location_name']); $location_name = nullable_htmlentities($row['location_name']);
$location_country = nullable_htmlentities($row['location_country']);
$location_address = nullable_htmlentities($row['location_address']);
$location_city = nullable_htmlentities($row['location_city']);
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$location_phone_country_code = nullable_htmlentities($row['location_phone_country_code']);
$location_phone = nullable_htmlentities(formatPhoneNumber($row['location_phone'], $location_phone_country_code));
if (empty($location_phone)) {
$location_phone_display = "-";
} else {
$location_phone_display = $location_phone;
}
$auth_method = nullable_htmlentities($row['user_auth_method']); $auth_method = nullable_htmlentities($row['user_auth_method']);
$contact_client_id = intval($row['contact_client_id']); $contact_client_id = intval($row['contact_client_id']);
@@ -153,7 +165,23 @@ if (isset($_GET['client_id'])) {
ob_start(); ob_start();
?> ?>
<div class="modal-header bg-dark"> <div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-user mr-2"></i><strong><?php echo $contact_name; ?></strong></h5> <h5 class="modal-title">
<div class="media">
<?php if ($contact_photo) { ?>
<img class="img-thumbnail img-circle img-size-50 mr-1" src="<?= "../uploads/clients/$client_id/$contact_photo" ?>">
<?php } else { ?>
<span class="fa-stack">
<i class="fa fa-circle fa-stack-2x text-secondary"></i>
<span class="fa fa-stack-1x text-white"><?= $contact_initials ?></span>
</span>
<?php } ?>
<div class="media-body ml-2">
<strong><?= $contact_name ?></strong>
<div class="text-sm"><?= $contact_title ?></div>
</div>
</div>
</h5>
<button type="button" class="close text-white" data-dismiss="modal"> <button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span> <span>&times;</span>
</button> </button>
@@ -161,142 +189,133 @@ ob_start();
<div class="modal-body"> <div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3"> <div class="row">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-contact-details<?php echo $contact_id; ?>"><i class="fas fa-fw fa-user fa-2x"></i><br>Details</a> <?php if ($contact_phone || $contact_mobile || $contact_extension || $contact_email) { ?>
</li> <div class="col-4">
<div class="media">
<i class="fas fa-fw fa-user fa-2x text-secondary"></i>
<div class="media-body ml-2">
<dt>Contact Details</dt>
<?php if ($contact_phone) { ?>
<div>
<i class="fas fa-fw fa-phone-alt text-secondary mt-2"></i>
<a href="tel:<?= $contact_phone ?>"><?= $contact_phone ?></a>
<?php if ($contact_extension) { ?>
<span>ext: <?= $contact_extension ?></span>
<?php } ?>
</div>
<?php } ?>
<?php if ($contact_mobile) { ?>
<div>
<i class="fas fa-fw fa-mobile-alt text-secondary mt-2"></i>
<a href="tel:<?= $contact_mobile ?>"><?= $contact_mobile ?></a>
</div>
<?php } ?>
<?php if ($contact_email) { ?>
<div>
<i class="fas fa-fw fa-envelope text-secondary mt-2"></i>
<a href='mailto:<?= $contact_email ?>'><?= $contact_email ?></a>
<button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?= $contact_email ?>'>
<i class='far fa-copy text-secondary'></i></button>
</div>
<?php } ?>
</div>
</div>
</div>
<?php } ?>
<?php if ($location_name) { ?>
<div class="col-4">
<div class="media">
<i class="fas fa-fw fa-map-marker-alt text-secondary fa-2x"></i>
<div class="media-body ml-2">
<dt><?= $location_name ?></dt>
<dd>
<div><?= $location_address ?></div>
<div><?= "$location_city $location_state $location_zip" ?></div>
<div><?= $location_country ?></div>
</dd>
</div>
</div>
</div>
<?php } ?>
<div class="col-4">
<div class="media">
<i class="fa fa-fw fa-info-circle text-secondary fa-2x"></i>
<div class="media-body ml-2">
<?php if ($contact_primary) { ?>
<span class="text-success text-bold">Primary Contact</span><br>
<?php } ?>
<?php if ($contact_billing) { ?>
<span class="text-dark font-weight-bold">Billing</span><br>
<?php } ?>
<?php if ($contact_technical) { ?>
<span class="text-secondary">Technical</span><br>
<?php } ?>
<?php if ($contact_important) { ?>
<span class="text-dark font-weight-bold">Important</span>
<?php } ?>
<?php if ($contact_pin) { ?>
<div>
Pin: <?= $contact_pin ?>
</div>
<?php } ?>
</div>
</div>
</div>
</div>
<ul class="nav nav-pills nav-justified mt-3">
<?php if ($asset_count) { ?> <?php if ($asset_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-assets<?php echo $contact_id; ?>"><i class="fas fa-fw fa-desktop fa-2x"></i><br>Assets (<?php echo $asset_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-assets<?= $contact_id ?>"><i class="fas fa-fw fa-desktop fa-2x"></i><br>Assets (<?= $asset_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($credential_count) { ?> <?php if ($credential_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-credentials<?php echo $contact_id; ?>"><i class="fas fa-fw fa-key fa-2x"></i><br>Credentials (<?php echo $credential_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-credentials<?= $contact_id ?>"><i class="fas fa-fw fa-key fa-2x"></i><br>Credentials (<?= $credential_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($software_count) { ?> <?php if ($software_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-licenses<?php echo $contact_id; ?>"><i class="fas fa-fw fa-cube fa-2x"></i><br>Licenses (<?php echo $software_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-licenses<?= $contact_id ?>"><i class="fas fa-fw fa-cube fa-2x"></i><br>Licenses (<?= $software_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($ticket_count) { ?> <?php if ($ticket_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-tickets<?php echo $contact_id; ?>"><i class="fas fa-fw fa-life-ring fa-2x"></i><br>Tickets (<?php echo $ticket_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-tickets<?= $contact_id ?>"><i class="fas fa-fw fa-life-ring fa-2x"></i><br>Tickets (<?= $ticket_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($recurring_ticket_count) { ?> <?php if ($recurring_ticket_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-recurring-tickets<?php echo $contact_id; ?>"><i class="fas fa-fw fa-redo-alt fa-2x"></i><br>Rcr Tickets (<?php echo $recurring_ticket_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-recurring-tickets<?= $contact_id ?>"><i class="fas fa-fw fa-redo-alt fa-2x"></i><br>Rcr Tickets (<?= $recurring_ticket_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($document_count) { ?> <?php if ($document_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-documents<?php echo $contact_id; ?>"><i class="fas fa-fw fa-file-alt fa-2x"></i><br>Documents (<?php echo $document_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-documents<?= $contact_id ?>"><i class="fas fa-fw fa-file-alt fa-2x"></i><br>Documents (<?= $document_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($file_count) { ?> <?php if ($file_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-files<?php echo $contact_id; ?>"><i class="fas fa-fw fa-briefcase fa-2x"></i><br>Files (<?php echo $file_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-files<?= $contact_id ?>"><i class="fas fa-fw fa-briefcase fa-2x"></i><br>Files (<?= $file_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
<?php if ($note_count) { ?> <?php if ($note_count) { ?>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-notes<?php echo $contact_id; ?>"><i class="fas fa-fw fa-edit fa-2x"></i><br>Notes (<?php echo $note_count; ?>)</a> <a class="nav-link" data-toggle="pill" href="#pills-contact-notes<?= $contact_id ?>"><i class="fas fa-fw fa-edit fa-2x"></i><br>Notes (<?= $note_count ?>)</a>
</li> </li>
<?php } ?> <?php } ?>
</ul> </ul>
<hr>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane fade show active" id="pills-contact-details<?php echo $contact_id; ?>">
<div class="card card-dark">
<div class="card-body">
<h3 class="text-bold"><?php echo $contact_name; ?></h3>
<?php if ($contact_title) { ?>
<div class="text-secondary"><?php echo $contact_title; ?></div>
<?php } ?>
<div class="text-center">
<?php if ($contact_photo) { ?>
<img class="img-thumbnail img-circle col-3" alt="contact_photo" src="<?php echo "../uploads/clients/$client_id/$contact_photo"; ?>">
<?php } else { ?>
<span class="fa-stack fa-4x">
<i class="fa fa-circle fa-stack-2x text-secondary"></i>
<span class="fa fa-stack-1x text-white"><?php echo $contact_initials; ?></span>
</span>
<?php } ?>
</div>
<?php
if (!empty($contact_tags_display)) { ?>
<div class="mt-1">
<?php echo $contact_tags_display; ?>
</div>
<?php } ?>
<hr>
<?php if ($location_name) { ?>
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-2"></i><?php echo $location_name; ?></div>
<?php }
if ($contact_email) { ?>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<?php }
if ($contact_phone) { ?>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-2"></i><a href="tel:<?php echo "$contact_phone"?>"><?php echo $contact_phone; ?></a></div>
<?php }
if ($contact_extension) { ?>
<div class="ml-4">x<?php echo $contact_extension; ?></div>
<?php }
if ($contact_mobile) { ?>
<div class="mt-l"><i class="fa fa-fw fa-mobile-alt text-secondary mr-2"></i><a href="tel:<?php echo $contact_mobile; ?>"><?php echo $contact_mobile; ?></a></div>
<?php }
if ($contact_pin) { ?>
<div class="mt-2"><i class="fa fa-fw fa-key text-secondary mr-2"></i><?php echo $contact_pin; ?></div>
<?php }
if ($contact_primary) { ?>
<div class="mt-2 text-success"><i class="fa fa-fw fa-check mr-2"></i>Primary Contact</div>
<?php }
if ($contact_important) { ?>
<div class="mt-2 text-dark text-bold"><i class="fa fa-fw fa-check mr-2"></i>Important</div>
<?php }
if ($contact_technical) { ?>
<div class="mt-2"><i class="fa fa-fw fa-check text-secondary mr-2"></i>Technical</div>
<?php }
if ($contact_billing) { ?>
<div class="mt-2"><i class="fa fa-fw fa-check text-secondary mr-2"></i>Billing</div>
<?php } ?>
<div class="mt-2"><i class="fa fa-fw fa-clock text-secondary mr-2"></i><?php echo date('Y-m-d', strtotime($contact_created_at)); ?></div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<h5 class="card-title">Notes</h5>
</div>
<textarea class="form-control" rows=6 id="contactNotes" placeholder="Notes, eg Personal tidbits to spark convo, temperment, etc" onblur="updateContactNotes(<?php echo $contact_id ?>)"><?php echo $contact_notes ?></textarea>
</div>
</div>
<script>
function updateContactNotes(contact_id) {
var notes = document.getElementById("contactNotes").value;
// Send a POST request to ajax.php as ajax.php with data contact_set_notes=true, contact_id=NUM, notes=NOTES
jQuery.post(
"ajax.php",
{
contact_set_notes: 'TRUE',
contact_id: contact_id,
notes: notes
}
)
}
</script>
<?php if ($asset_count) { ?> <?php if ($asset_count) { ?>
<div class="tab-pane fade" id="pills-contact-assets<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-assets<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm"> <table class="table table-striped table-borderless table-hover table-sm">
@@ -361,28 +380,26 @@ ob_start();
?> ?>
<tr> <tr>
<th> <th>
<i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-2"></i> <i class="fa fa-fw text-secondary fa-<?= $device_icon ?> mr-2"></i>
<a class="text-secondary" href="#" <a href="#" class="ajax-modal"
data-toggle="ajax-modal"
data-modal-size="lg" data-modal-size="lg"
data-ajax-url="ajax/ajax_asset_details.php" data-modal-url="modals/asset/asset_details.php?id=<?= $asset_id ?>">
data-ajax-id="<?php echo $asset_id; ?>"> <?= $asset_name ?>
<?php echo $asset_name; ?>
</a> </a>
<div class="mt-0"> <div class="mt-0">
<small class="text-muted"><?php echo $asset_description; ?></small> <small class="text-muted"><?= $asset_description ?></small>
</div> </div>
</th> </th>
<td><?php echo $asset_type; ?></td> <td><?= $asset_type ?></td>
<td> <td>
<?php echo $asset_make; ?> <?= $asset_make ?>
<div class="mt-0"> <div class="mt-0">
<small class="text-muted"><?php echo $asset_model; ?></small> <small class="text-muted"><?= $asset_model ?></small>
</div> </div>
</td> </td>
<td><?php echo $asset_serial_display; ?></td> <td><?= $asset_serial_display ?></td>
<td><?php echo $asset_install_date_display; ?></td> <td><?= $asset_install_date_display ?></td>
<td><?php echo $asset_status; ?></td> <td><?= $asset_status ?></td>
</tr> </tr>
<?php <?php
@@ -398,7 +415,7 @@ ob_start();
<?php } ?> <?php } ?>
<?php if ($credential_count) { ?> <?php if ($credential_count) { ?>
<div class="tab-pane fade" id="pills-contact-credentials<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-credentials<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm dataTables" style="width:100%"> <table class="table table-striped table-borderless table-hover table-sm dataTables" style="width:100%">
<thead> <thead>
@@ -468,16 +485,16 @@ ob_start();
?> ?>
<tr> <tr>
<td><i class="fa fa-fw fa-key text-secondary mr-2"></i><?php echo $credential_name; ?></td> <td><i class="fa fa-fw fa-key text-secondary mr-2"></i><?= $credential_name ?></td>
<td><?php echo $credential_description; ?></td> <td><?= $credential_description ?></td>
<td><?php echo $credential_username_display; ?></td> <td><?= $credential_username_display ?></td>
<td> <td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button> <button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?= $credential_password ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $credential_password; ?>'><i class='far fa-copy text-secondary'></i></button> <button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?= $credential_password ?>'><i class='far fa-copy text-secondary'></i></button>
</td> </td>
<td><?php echo $otp_display; ?></td> <td><?= $otp_display ?></td>
<td><?php echo $credential_uri_display; ?></td> <td><?= $credential_uri_display ?></td>
</tr> </tr>
<?php <?php
@@ -495,7 +512,7 @@ ob_start();
<?php } ?> <?php } ?>
<?php if ($ticket_count) { ?> <?php if ($ticket_count) { ?>
<div class="tab-pane fade" id="pills-contact-tickets<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-tickets<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm"> <table class="table table-striped table-borderless table-hover table-sm">
<thead class="text-dark"> <thead class="text-dark">
@@ -557,13 +574,13 @@ ob_start();
?> ?>
<tr> <tr>
<td><a href="ticket.php?client_id=<?php echo $client_id; ?>&ticket_id=<?php echo $ticket_id; ?>"><span class="badge badge-pill badge-secondary p-3"><?php echo "$ticket_prefix$ticket_number"; ?></span></a></td> <td><a href="ticket.php?client_id=<?= $client_id ?>&ticket_id=<?= $ticket_id ?>"><span class="badge badge-pill badge-secondary p-3"><?= "$ticket_prefix$ticket_number" ?></span></a></td>
<td><a href="ticket.php?client_id=<?php echo $client_id; ?>&ticket_id=<?php echo $ticket_id; ?>"><?php echo $ticket_subject; ?></a></td> <td><a href="ticket.php?client_id=<?= $client_id ?>&ticket_id=<?= $ticket_id ?>"><?= $ticket_subject ?></a></td>
<td><?php echo $ticket_priority_display; ?></td> <td><?= $ticket_priority_display ?></td>
<td><span class='badge badge-pill text-light p-2' style="background-color: <?php echo $ticket_status_color; ?>"><?php echo $ticket_status_name; ?></span></td> <td><span class='badge badge-pill text-light p-2' style="background-color: <?= $ticket_status_color ?>"><?= $ticket_status_name ?></span></td>
<td><?php echo $ticket_assigned_to_display; ?></td> <td><?= $ticket_assigned_to_display ?></td>
<td><?php echo $ticket_updated_at_display; ?></td> <td><?= $ticket_updated_at_display ?></td>
<td><?php echo $ticket_created_at; ?></td> <td><?= $ticket_created_at ?></td>
</tr> </tr>
<?php <?php
@@ -579,7 +596,7 @@ ob_start();
<?php } ?> <?php } ?>
<?php if ($recurring_ticket_count) { ?> <?php if ($recurring_ticket_count) { ?>
<div class="tab-pane fade" id="pills-contact-recurring-tickets<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-recurring-tickets<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm"> <table class="table table-striped table-borderless table-hover table-sm">
@@ -603,10 +620,10 @@ ob_start();
?> ?>
<tr> <tr>
<td class="text-bold"><?php echo $recurring_ticket_subject ?></td> <td class="text-bold"><?= $recurring_ticket_subject ?></td>
<td><?php echo $recurring_ticket_priority ?></td> <td><?= $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td> <td><?= $recurring_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_next_run ?></td> <td><?= $recurring_ticket_next_run ?></td>
</tr> </tr>
<?php } ?> <?php } ?>
@@ -618,7 +635,7 @@ ob_start();
<?php } ?> <?php } ?>
<?php if ($software_count) { ?> <?php if ($software_count) { ?>
<div class="tab-pane fade" id="pills-contact-licenses<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-licenses<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm"> <table class="table table-striped table-borderless table-hover table-sm">
<thead class="text-dark"> <thead class="text-dark">
@@ -668,10 +685,10 @@ ob_start();
?> ?>
<tr> <tr>
<td><?php echo "$software_name $software_version"; ?></td> <td><?= "$software_name $software_version" ?></td>
<td><?php echo $software_type; ?></td> <td><?= $software_type ?></td>
<td><?php echo $software_key; ?></td> <td><?= $software_key ?></td>
<td><?php echo "$seat_count / $software_seats"; ?></td> <td><?= "$seat_count / $software_seats" ?></td>
</tr> </tr>
<?php <?php
@@ -687,7 +704,7 @@ ob_start();
<?php } ?> <?php } ?>
<?php if ($document_count) { ?> <?php if ($document_count) { ?>
<div class="tab-pane fade" id="pills-contact-documents<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-documents<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm"> <table class="table table-striped table-borderless table-hover table-sm">
@@ -721,11 +738,11 @@ ob_start();
data-modal-url="modals/document/document_view.php?id=<?= $document_id ?>"> data-modal-url="modals/document/document_view.php?id=<?= $document_id ?>">
<?php echo $document_name; ?> <?php echo $document_name; ?>
</a> </a>
<div class="text-secondary"><?php echo $document_description; ?></div> <div class="text-secondary"><?= $document_description ?></div>
</td> </td>
<td><?php echo $document_created_by; ?></td> <td><?= $document_created_by ?></td>
<td><?php echo $document_created_at; ?></td> <td><?= $document_created_at ?></td>
<td><?php echo $document_updated_at; ?></td> <td><?= $document_updated_at ?></td>
</tr> </tr>
<?php <?php
@@ -741,7 +758,7 @@ ob_start();
<?php } ?> <?php } ?>
<?php if ($file_count) { ?> <?php if ($file_count) { ?>
<div class="tab-pane fade" id="pills-contact-files<?php echo $contact_id; ?>"> <div class="tab-pane fade" id="pills-contact-files<?= $contact_id ?>">
<div class="table-responsive-sm"> <div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm"> <table class="table table-striped table-borderless table-hover table-sm">
<thead class="text-dark"> <thead class="text-dark">
@@ -771,12 +788,12 @@ ob_start();
<tr> <tr>
<td> <td>
<div><a href="../uploads/clients/<?php echo $client_id; ?>/<?php echo $file_reference_name; ?>"><?php echo $file_name; ?></a></div> <div><a href="../uploads/clients/<?= $client_id ?>/<?= $file_reference_name ?>" target="_blank"><?= $file_name ?></a></div>
<div class="text-secondary"><?php echo $file_description; ?></div> <div class="text-secondary"><?= $file_description ?></div>
</td> </td>
<td><?php echo $file_mime_type; ?></td> <td><?= $file_mime_type ?></td>
<td><?php echo $file_size_KB; ?> KB</td> <td><?= $file_size_KB ?> KB</td>
<td><?php echo $file_created_at; ?></td> <td><?= $file_created_at ?></td>
</tr> </tr>
<?php <?php
@@ -819,10 +836,10 @@ ob_start();
?> ?>
<tr> <tr>
<td><i class="fa fa-fw <?php echo $note_type_icon; ?> mr-2"></i><?php echo $contact_note_type; ?></td> <td><i class="fa fa-fw <?= $note_type_icon ?> mr-2"></i><?= $contact_note_type ?></td>
<td><?php echo $contact_note; ?></td> <td><?= $contact_note ?></td>
<td><?php echo $note_by; ?></td> <td><?= $note_by ?></td>
<td><?php echo $contact_note_created_at; ?></td> <td><?= $contact_note_created_at ?></td>
</tr> </tr>
<?php <?php
@@ -842,14 +859,13 @@ ob_start();
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="contact_details.php?client_id=<?php echo $client_id; ?>&contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold"> <a href="contact_details.php?client_id=<?= $client_id ?>&contact_id=<?= $contact_id ?>" class="btn btn-outline-primary">
<span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span> <i class="fas fa-info-circle mr-2"></i>More Details
</a> </a>
<a href="#" class="btn btn-secondary" <a href="#" class="btn btn-secondary ajax-modal"
data-toggle="ajax-modal" data-ajax-url="ajax/ajax_contact_edit.php" data-ajax-id="<?php echo $contact_id; ?>"> data-modal-url="modals/contact/contact_edit.php?id=<?= $contact_id ?>">
<span class="text-white"><i class="fas fa-edit mr-2"></i>Edit</span> <i class="fas fa-edit mr-2"></i>Edit
</a> </a>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Close</button>
</div> </div>
<?php <?php

View File

@@ -12,7 +12,7 @@
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>"> <input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?> <?php } ?>
<div class="modal-body"> <div class="modal-body">
<p><strong>Format csv file with headings & data:</strong><br>Name, Description, Username, Password, URL</p> <p><strong>Format csv file with headings & data:</strong><br>Name, Description, Username, Password, TOTP, URI</p>
<hr> <hr>
<div class="form-group my-4"> <div class="form-group my-4">
<input type="file" class="form-control-file" name="file" accept=".csv" required> <input type="file" class="form-control-file" name="file" accept=".csv" required>

View File

@@ -113,7 +113,7 @@
$sql = mysqli_query( $sql = mysqli_query(
$mysqli, $mysqli,
"SELECT user_id, user_name FROM users "SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC" WHERE user_type = 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
); );
while ($row = mysqli_fetch_array($sql)) { while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']); $user_id = intval($row['user_id']);
@@ -190,11 +190,17 @@
<span class="input-group-text"><i class="fa fa-fw fa-recycle"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-recycle"></i></span>
</div> </div>
<select class="form-control select2" name="frequency" required> <select class="form-control select2" name="frequency" required>
<optgroup label="Days">
<option>Three Days</option>
<option>Weekly</option> <option>Weekly</option>
<option>Biweekly</option>
</optgroup>
<optgroup label="Months">
<option>Monthly</option> <option>Monthly</option>
<option>Quarterly</option> <option>Quarterly</option>
<option>Biannually</option> <option>Biannually</option>
<option>Annually</option> <option>Annually</option>
</optgroup>
</select> </select>
</div> </div>
</div> </div>
@@ -223,21 +229,46 @@
</div> </div>
<select class="form-control select2" name="asset"> <select class="form-control select2" name="asset">
<option value="0">- None -</option> <option value="0">- None -</option>
<?php <?php
$sql_assets = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_client_id = $client_id AND asset_archived_at IS NULL ORDER BY asset_name ASC"); // Query assets ordered by type, then name
$sql_assets = mysqli_query($mysqli, "
SELECT asset_id, asset_name, asset_type, asset_make, asset_model, contact_name
FROM assets
LEFT JOIN contacts ON contact_id = asset_contact_id
WHERE asset_client_id = $client_id
AND asset_archived_at IS NULL
ORDER BY asset_type ASC, asset_name ASC
");
$current_type = null; // Track which optgroup we're in
while ($row = mysqli_fetch_array($sql_assets)) { while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id_select = intval($row['asset_id']); $asset_id_select = intval($row['asset_id']);
$asset_name_select = nullable_htmlentities($row['asset_name']); $asset_name_select = nullable_htmlentities($row['asset_name']);
?> $asset_type_select = nullable_htmlentities($row['asset_type']);
<option value="<?php echo $asset_id_select; ?>" $asset_make_select = nullable_htmlentities($row['asset_make']);
<?php if (isset($_GET['asset_id']) && $asset_id_select == $_GET['asset_id']) { echo "selected"; } $asset_model_select = nullable_htmlentities($row['asset_model']);
$contact_name_select = nullable_htmlentities($row['contact_name']);
// Start new optgroup if type changes
if ($asset_type_select !== $current_type) {
if ($current_type !== null) echo "</optgroup>";
echo "<optgroup label=\"" . ($asset_type_select ?: 'Uncategorized') . "\">";
$current_type = $asset_type_select;
}
// Build full display
$full_name = $asset_name_select . ($asset_make_select ? " - $asset_make_select" . ($asset_model_select ? " $asset_model_select" : '') : '')
. ($contact_name_select ? " - ($contact_name_select)" : '');
?> ?>
><?php echo $asset_name_select; ?> <option value="<?= $asset_id_select ?>"><?= $full_name ?></option>
</option>
<?php } ?> <?php }
if ($current_type_select !== null) echo "</optgroup>";
?>
</select> </select>
</div> </div>
</div> </div>
@@ -250,23 +281,51 @@
</div> </div>
<select class="form-control select2" name="additional_assets[]" data-tags="true" data-placeholder="- Select Additional Assets -" multiple> <select class="form-control select2" name="additional_assets[]" data-tags="true" data-placeholder="- Select Additional Assets -" multiple>
<option value=""></option> <option value=""></option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, contact_name FROM assets LEFT JOIN contacts ON contact_id = asset_contact_id WHERE asset_client_id = $client_id AND asset_archived_at IS NULL ORDER BY asset_name ASC"); <?php
// Query assets ordered by type then name
$sql_assets = mysqli_query($mysqli, "
SELECT asset_id, asset_name, asset_type, asset_make, asset_model, contact_name
FROM assets
LEFT JOIN contacts ON contact_id = asset_contact_id
WHERE asset_client_id = $client_id
AND asset_archived_at IS NULL
ORDER BY asset_type ASC, asset_name ASC
");
$current_type = null;
while ($row = mysqli_fetch_array($sql_assets)) { while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id_select = intval($row['asset_id']); $asset_id_select = intval($row['asset_id']);
$asset_name_select = nullable_htmlentities($row['asset_name']); $asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']); $asset_type_select = nullable_htmlentities($row['asset_type']);
?> $asset_make_select = nullable_htmlentities($row['asset_make']);
<option value="<?php echo $asset_id_select; ?>" $asset_model_select = nullable_htmlentities($row['asset_model']);
><?php echo "$asset_name_select - $asset_contact_name_select"; ?> $contact_name_select = nullable_htmlentities($row['contact_name']);
</option>
<?php } ?> // Start new optgroup if type changes
if ($asset_type_select !== $current_type) {
if ($current_type !== null) echo "</optgroup>";
echo "<optgroup label=\"" . ($asset_type_select ?: 'Uncategorized') . "\">";
$current_type = $asset_type_select;
}
// Build full display
$full_name = $asset_name_select . ($asset_make_select ? " - $asset_make_select" . ($asset_model_select ? " $asset_model_select" : '') : '')
. ($contact_name_select ? " - ($contact_name_select)" : '');
?>
<option value="<?= $asset_id_select ?>"><?= $full_name ?></option>
<?php }
if ($current_type !== null) echo "</optgroup>";
?>
</select> </select>
</div> </div>
</div> </div>
<?php } ?> <?php } ?>
</div> </div>

View File

@@ -0,0 +1,46 @@
<div class="modal" id="bulkAssignAgentRecurringTicketModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-user-check mr-2"></i>Assigning Agent</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Assign Agent</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user-check"></i></span>
</div>
<select class="form-control select2" name="assign_to">
<option value="0">Not Assigned</option>
<?php
$sql_users_select = mysqli_query($mysqli, "SELECT user_id, user_name FROM users
WHERE user_type = 1
AND user_status = 1
AND user_archived_at IS NULL
ORDER BY user_name DESC"
);
while ($row = mysqli_fetch_array($sql_users_select)) {
$user_id_select = intval($row['user_id']);
$user_name_select = nullable_htmlentities($row['user_name']);
?>
<option value="<?= $user_id_select ?>"><?= $user_name_select ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="bulk_assign_recurring_ticket" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,29 @@
<div class="modal" id="bulkEditBillableRecurringTicketModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-money mr-2"></i>Bulk Set Billable</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="billable" value="1" id="billable<?= $recurring_ticket_id ?>">
<label class="custom-control-label" for="billable<?= $recurring_ticket_id ?>">Mark Billable</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="bulk_edit_recurring_ticket_billable" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,42 @@
<div class="modal" id="bulkEditCategoryRecurringTicketModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-layer-group mr-2"></i>Bulk Set Category</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Category</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-layer-group"></i></span>
</div>
<select class="form-control select2" name="bulk_category">
<option value="0">- Uncategorized -</option>
<?php
$sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_categories)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
?>
<option value="<?php echo $category_id; ?>"><?php echo $category_name; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="bulk_edit_recurring_ticket_category" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,32 @@
<div class="modal" id="bulkEditNextRunRecurringTicketModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-calendar-day mr-2"></i>Set Next Run Date</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Next Run Date <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar-day"></i></span>
</div>
<input class="form-control" type="date" name="next_run_date" min="<?= date("Y-m-d"); ?>" max="2999-12-31">
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="bulk_edit_recurring_ticket_next_run_date" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,36 @@
<div class="modal" id="bulkEditPriorityRecurringTicketModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-thermometer-half mr-2"></i>Bulk Editing Priority</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Priority</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-thermometer-half"></i></span>
</div>
<select class="form-control select2" name="bulk_priority">
<option>Low</option>
<option>Medium</option>
<option>High</option>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="bulk_edit_recurring_ticket_priority" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</div>
</div>
</div>

View File

@@ -136,7 +136,7 @@ ob_start();
$sql_users_select = mysqli_query($mysqli, "SELECT user_id, user_name FROM users $sql_users_select = mysqli_query($mysqli, "SELECT user_id, user_name FROM users
WHERE user_type = 1 WHERE user_type = 1
AND user_archived_at IS NULL AND user_archived_at IS NULL
ORDER BY user_name DESC" ORDER BY user_name ASC"
); );
while ($row = mysqli_fetch_array($sql_users_select)) { while ($row = mysqli_fetch_array($sql_users_select)) {
$user_id_select = intval($row['user_id']); $user_id_select = intval($row['user_id']);
@@ -212,7 +212,9 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-recycle"></i></span> <span class="input-group-text"><i class="fa fa-fw fa-recycle"></i></span>
</div> </div>
<select class="form-control select2" name="frequency"> <select class="form-control select2" name="frequency">
<option <?php if ($recurring_ticket_frequency == "Three Days") { echo "selected"; } ?>>Three Days</option>
<option <?php if ($recurring_ticket_frequency == "Weekly") { echo "selected"; } ?>>Weekly</option> <option <?php if ($recurring_ticket_frequency == "Weekly") { echo "selected"; } ?>>Weekly</option>
<option <?php if ($recurring_ticket_frequency == "Biweekly") { echo "selected"; } ?>>Biweekly</option>
<option <?php if ($recurring_ticket_frequency == "Monthly") { echo "selected"; } ?>>Monthly</option> <option <?php if ($recurring_ticket_frequency == "Monthly") { echo "selected"; } ?>>Monthly</option>
<option <?php if ($recurring_ticket_frequency == "Quarterly") { echo "selected"; } ?>>Quarterly</option> <option <?php if ($recurring_ticket_frequency == "Quarterly") { echo "selected"; } ?>>Quarterly</option>
<option <?php if ($recurring_ticket_frequency == "Biannually") { echo "selected"; } ?>>Biannually</option> <option <?php if ($recurring_ticket_frequency == "Biannually") { echo "selected"; } ?>>Biannually</option>

View File

@@ -185,8 +185,7 @@
$sql = mysqli_query( $sql = mysqli_query(
$mysqli, $mysqli,
"SELECT user_id, user_name FROM users "SELECT user_id, user_name FROM users
WHERE user_role_id > 1 WHERE user_type = 1
AND user_type = 1
AND user_status = 1 AND user_status = 1
AND user_archived_at IS NULL AND user_archived_at IS NULL
ORDER BY user_name ASC" ORDER BY user_name ASC"

View File

@@ -160,7 +160,7 @@
$sql = mysqli_query( $sql = mysqli_query(
$mysqli, $mysqli,
"SELECT user_id, user_name FROM users "SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC" WHERE user_type = 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
); );
while ($row = mysqli_fetch_array($sql)) { while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']); $user_id = intval($row['user_id']);

View File

@@ -44,11 +44,10 @@ ob_start();
<select class="form-control select2" name="assigned_to"> <select class="form-control select2" name="assigned_to">
<option value="0">Not Assigned</option> <option value="0">Not Assigned</option>
<?php <?php
$sql_users_select = mysqli_query($mysqli, "SELECT users.user_id, user_name FROM users $sql_users_select = mysqli_query($mysqli, "SELECT user_id, user_name FROM users
LEFT JOIN user_settings on users.user_id = user_settings.user_id
WHERE user_type = 1 WHERE user_type = 1
AND user_archived_at IS NULL AND user_archived_at IS NULL
ORDER BY user_name DESC" ORDER BY user_name ASC"
); );
while ($row = mysqli_fetch_array($sql_users_select)) { while ($row = mysqli_fetch_array($sql_users_select)) {
$user_id_select = intval($row['user_id']); $user_id_select = intval($row['user_id']);

View File

@@ -22,7 +22,7 @@
WHERE user_type = 1 WHERE user_type = 1
AND user_status = 1 AND user_status = 1
AND user_archived_at IS NULL AND user_archived_at IS NULL
ORDER BY user_name DESC" ORDER BY user_name ASC"
); );
while ($row = mysqli_fetch_array($sql_users_select)) { while ($row = mysqli_fetch_array($sql_users_select)) {
$user_id_select = intval($row['user_id']); $user_id_select = intval($row['user_id']);

View File

@@ -0,0 +1,65 @@
<?php
require_once '../../../includes/modal_header.php';
$ticket_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM tickets LEFT JOIN clients ON client_id = ticket_client_id WHERE ticket_id = $ticket_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['ticket_client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$ticket_prefix = nullable_htmlentities($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_project_id = intval($row['ticket_project_id']);
// Select box arrays
$sql_projects = mysqli_query($mysqli, "SELECT project_id, project_name FROM projects WHERE (project_client_id = $client_id OR project_client_id = 0) AND project_completed_at IS NULL AND project_archived_at IS NULL ORDER BY project_name ASC");
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-project-diagram mr-2"></i>Project: <strong><?= "$ticket_prefix$ticket_number" ?></strong> - <?= $client_name ?></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_id" value="<?php echo $ticket_id; ?>">
<div class="modal-body">
<div class="form-group">
<label>Project</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-project-diagram"></i></span>
</div>
<select class="form-control select2" name="project">
<option value="0">- None -</option>
<?php
while ($row = mysqli_fetch_array($sql_projects)) {
$project_id = intval($row['project_id']);
$project_name = nullable_htmlentities($row['project_name']); ?>
<option <?php if ($ticket_project_id == $project_id) { echo "selected"; } ?>
value="<?= $project_id ?>"><?= $project_name ?>
</option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_ticket_project" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -51,7 +51,7 @@ ob_start();
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div><strong>Code:</strong> <?php echo getFallback($code); ?></div> <div><strong>Code:</strong> <?php echo getFallback($code); ?></div>
<div><strong>Website:</strong> <?php echo !empty($website) ? '<a href="' . $website . '" target="_blank" class="text-primary">' . $website . '</a>' : '<span class="text-muted">Not Available</span>'; ?></div> <div><strong>Website:</strong> <?php echo !empty($website) ? '<a href="https://' . $website . '" target="_blank" class="text-primary">' . $website . '</a>' : '<span class="text-muted">Not Available</span>'; ?></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -123,34 +123,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -26,7 +26,7 @@ $module = str_ireplace('_details', '', $module);
// Dynamically load admin-related module POST logic // Dynamically load admin-related module POST logic
// Load all module POST logic // Load all module POST logic
// Loads everything in post/user/ // Loads everything in post
// Eventually, it would be nice to only specifically load what we need like we do for admins // Eventually, it would be nice to only specifically load what we need like we do for admins
foreach (glob("post/*.php") as $user_module) { foreach (glob("post/*.php") as $user_module) {

View File

@@ -787,10 +787,10 @@ if (isset($_POST["import_assets_csv"])) {
flash_alert("Bad file size (empty?)", 'error'); flash_alert("Bad file size (empty?)", 'error');
} }
//(Else)Check column count (name, desc, type, make, model, serial, os, purchase date, assigned to, location) //(Else)Check column count (name, desc, type, make, model, serial, os, purchase date, assigned to, location, notes)
$f = fopen($file_name, "r"); $f = fopen($file_name, "r");
$f_columns = fgetcsv($f, 1000, ","); $f_columns = fgetcsv($f, 1000, ",");
if (!$error & count($f_columns) != 11) { if (!$error & count($f_columns) != 12) {
$error = true; $error = true;
flash_alert("Invalid column count.", 'error'); flash_alert("Invalid column count.", 'error');
} }
@@ -884,10 +884,15 @@ if (isset($_POST["import_assets_csv"])) {
$physical_location = sanitizeInput($column[10]); $physical_location = sanitizeInput($column[10]);
} }
// Notes (varchar)
if (!empty($column[11])) {
$notes = sanitizeInput($column[11]);
}
// Check if duplicate was detected // Check if duplicate was detected
if ($duplicate_detect == 0) { if ($duplicate_detect == 0) {
//Add //Add
mysqli_query($mysqli,"INSERT INTO assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_purchase_date = $purchase_date, asset_physical_location = '$physical_location', asset_contact_id = $contact_id, asset_location_id = $location_id, asset_client_id = $client_id"); mysqli_query($mysqli,"INSERT INTO assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_purchase_date = $purchase_date, asset_physical_location = '$physical_location', asset_notes = '$notes', asset_contact_id = $contact_id, asset_location_id = $location_id, asset_client_id = $client_id");
$asset_id = mysqli_insert_id($mysqli); $asset_id = mysqli_insert_id($mysqli);
@@ -932,7 +937,7 @@ if (isset($_GET['download_assets_csv_template'])) {
$f = fopen('php://memory', 'w'); $f = fopen('php://memory', 'w');
//set column headers //set column headers
$fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial', 'OS', 'Purchase Date', 'Assigned To', 'Location', 'Physical Location'); $fields = array('Name', 'Description', 'Type', 'Make', 'Model', 'Serial', 'OS', 'Purchase Date', 'Assigned To', 'Location', 'Physical Location', 'Notes');
fputcsv($f, $fields, $delimiter); fputcsv($f, $fields, $delimiter);
//move back to beginning of file //move back to beginning of file

View File

@@ -1,61 +0,0 @@
<?php
/*
* ITFlow - GET/POST request handler for budget
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['save_budget'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_financial', 2);
$budgets = $_POST['budget'];
$year = intval($_POST['year']);
foreach ($budgets as $category_id => $months) {
foreach ($months as $month => $amount) {
$amount = (int)$amount;
// Check if budget exists
$query = "SELECT * FROM budget WHERE budget_category_id = $category_id AND budget_month = $month AND budget_year = $year";
$result = mysqli_query($mysqli, $query);
if (mysqli_num_rows($result) > 0) {
// Update existing budget
$query = "UPDATE budget SET budget_amount = $amount WHERE budget_category_id = $category_id AND budget_month = $month AND budget_year = $year";
} else {
// Insert new budget
$query = "INSERT INTO budget SET budget_category_id = $category_id, budget_month = $month, budget_year = $year, budget_amount = $amount";
}
mysqli_query($mysqli, $query);
}
}
logAction("Budget", "Edit", "$session_name edited the budget for $year");
flash_alert("Budget Updated for $year");
redirect();
}
if (isset($_POST['delete_budget'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_financial', 3);
$year = intval($_POST['year']);
mysqli_query($mysqli,"DELETE FROM budget WHERE budget_year = $year");
logAction("Budget", "Delete", "$session_name deleted the budget for $year");
flash_alert("Budget deleted for $year", 'error');
redirect();
}

View File

@@ -120,7 +120,7 @@ if (isset($_GET['archive_certificate'])) {
mysqli_query($mysqli,"UPDATE certificates SET certificate_archived_at = NOW() WHERE certificate_id = $certificate_id"); mysqli_query($mysqli,"UPDATE certificates SET certificate_archived_at = NOW() WHERE certificate_id = $certificate_id");
logAction("Certificate", "Archive", "$session_name arhvived certificate $certificate_name", $client_id, $certificate_id); logAction("Certificate", "Archive", "$session_name archived certificate $certificate_name", $client_id, $certificate_id);
flash_alert("Certificate <strong>$certificate_name</strong> archived", 'alert'); flash_alert("Certificate <strong>$certificate_name</strong> archived", 'alert');

View File

@@ -40,9 +40,9 @@ if (isset($_POST['add_client'])) {
$client_id = mysqli_insert_id($mysqli); $client_id = mysqli_insert_id($mysqli);
if (!file_exists("../uploads/clients/$client_id")) { if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/uploads/clients/$client_id")) {
mkdir("../uploads/clients/$client_id"); mkdir($_SERVER['DOCUMENT_ROOT'] . "/uploads/clients/$client_id");
file_put_contents("../uploads/clients/$client_id/index.php", ""); file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/uploads/clients/$client_id/index.php", "");
} }
// Create Referral if it doesn't exist // Create Referral if it doesn't exist
@@ -171,11 +171,20 @@ if (isset($_GET['archive_client'])) {
$client_id = intval($_GET['archive_client']); $client_id = intval($_GET['archive_client']);
// Archive client
mysqli_query($mysqli, "UPDATE clients SET client_archived_at = NOW() WHERE client_id = $client_id");
// Stop recurring invoices
$sql_recurring_invoices = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_client_id = $client_id AND recurring_invoice_status = 1");
while ($row = mysqli_fetch_array($sql_recurring_invoices)) {
$recurring_invoice_id = intval($row['recurring_invoice_id']);
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_status = 0 WHERE recurring_invoice_id = $recurring_invoice_id AND recurring_invoice_client_id = $client_id");
mysqli_query($mysqli,"INSERT INTO history SET history_status = 0, history_description = 'Recurring Invoice inactive as client archived', history_recurring_invoice_id = $recurring_invoice_id");
}
// Get Client Name // Get Client Name
$client_name = sanitizeInput(getFieldById('clients', $client_id, 'client_name')); $client_name = sanitizeInput(getFieldById('clients', $client_id, 'client_name'));
mysqli_query($mysqli, "UPDATE clients SET client_archived_at = NOW() WHERE client_id = $client_id");
logAction("Client", "Archive", "$session_name archived client $client_name", $client_id, $client_id); logAction("Client", "Archive", "$session_name archived client $client_name", $client_id, $client_id);
flash_alert("Client <strong>$client_name</strong> archived", 'error'); flash_alert("Client <strong>$client_name</strong> archived", 'error');
@@ -589,6 +598,120 @@ if (isset($_GET['download_clients_csv_template'])) {
} }
if (isset($_POST['bulk_add_client_ticket'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_support', 2);
$assigned_to = intval($_POST['bulk_assigned_to']);
if ($assigned_to == 0) {
$ticket_status = 1;
} else {
$ticket_status = 2;
}
$subject = sanitizeInput($_POST['bulk_subject']);
$priority = sanitizeInput($_POST['bulk_priority']);
$category_id = intval($_POST['bulk_category']);
$details = mysqli_real_escape_string($mysqli, $_POST['bulk_details']);
$project_id = intval($_POST['bulk_project']);
$use_primary_contact = intval($_POST['use_primary_contact']);
$ticket_template_id = intval($_POST['bulk_ticket_template_id']);
$billable = intval($_POST['bulk_billable'] ?? 0);
// Check to see if adding a ticket by template
if($ticket_template_id) {
$sql = mysqli_query($mysqli, "SELECT * FROM ticket_templates WHERE ticket_template_id = $ticket_template_id");
$row = mysqli_fetch_array($sql);
// Override Template Subject
if(empty($subject)) {
$subject = sanitizeInput($row['ticket_template_subject']);
}
$details = mysqli_escape_string($mysqli, $row['ticket_template_details']);
// Get Associated Tasks from the ticket template
$sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id");
}
// Create ticket for each selected asset
if (isset($_POST['client_ids'])) {
// Get a Asset Count
$client_count = count($_POST['client_ids']);
foreach ($_POST['client_ids'] as $client_id) {
$client_id = intval($client_id);
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_id = $client_id");
$row = mysqli_fetch_array($sql);
$client_name = sanitizeInput($row['client_name']);
// Get the next Ticket Number and update the config
$sql_ticket_number = mysqli_query($mysqli, "SELECT config_ticket_next_number FROM settings WHERE company_id = 1");
$ticket_number_row = mysqli_fetch_array($sql_ticket_number);
$ticket_number = intval($ticket_number_row['config_ticket_next_number']);
// Sanitize Config Vars from get_settings.php and Session Vars from check_login.php
$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_base_url = sanitizeInput($config_base_url);
//Generate a unique URL key for clients to access
$url_key = randomString(156);
// Increment the config ticket next number
$new_config_ticket_next_number = $ticket_number + 1;
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_category = $category_id, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_billable = $billable, ticket_status = $ticket_status, ticket_created_by = $session_user_id, ticket_assigned_to = $assigned_to, ticket_url_key = '$url_key', ticket_client_id = $client_id, ticket_project_id = $project_id");
$ticket_id = mysqli_insert_id($mysqli);
// Update the next ticket number in the database
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
// Add Tasks
if (!empty($_POST['tasks'])) {
foreach ($_POST['tasks'] as $task) {
$task_name = sanitizeInput($task);
// Check that task_name is not-empty (For some reason the !empty on the array doesnt work here like in watchers)
if (!empty($task_name)) {
mysqli_query($mysqli,"INSERT INTO tasks SET task_name = '$task_name', task_ticket_id = $ticket_id");
}
}
}
// Add Tasks from Template if Template was selected
if($ticket_template_id) {
if (mysqli_num_rows($sql_task_templates) > 0) {
while ($row = mysqli_fetch_array($sql_task_templates)) {
$task_order = intval($row['task_template_order']);
$task_name = sanitizeInput($row['task_template_name']);
mysqli_query($mysqli,"INSERT INTO tasks SET task_name = '$task_name', task_order = $task_order, task_ticket_id = $ticket_id");
}
}
}
// Custom action/notif handler
customAction('ticket_create', $ticket_id);
}
logAction("Ticket", "Bulk Create", "$session_name created $client_count tickets for $client_name");
flash_alert("<strong>$client_count</strong> tickets created for selected clients");
}
redirect();
}
if (isset($_POST['bulk_edit_client_industry'])) { if (isset($_POST['bulk_edit_client_industry'])) {
validateCSRFToken($_POST['csrf_token']); validateCSRFToken($_POST['csrf_token']);

View File

@@ -317,8 +317,6 @@ if (isset($_POST['export_credentials_csv'])) {
//get records from database //get records from database
$sql = mysqli_query($mysqli,"SELECT * FROM credentials LEFT JOIN clients ON client_id = credential_client_id WHERE credential_archived_at IS NULL $client_query ORDER BY credential_name ASC"); $sql = mysqli_query($mysqli,"SELECT * FROM credentials LEFT JOIN clients ON client_id = credential_client_id WHERE credential_archived_at IS NULL $client_query ORDER BY credential_name ASC");
$row = mysqli_fetch_array($sql);
$num_rows = mysqli_num_rows($sql); $num_rows = mysqli_num_rows($sql);
if ($num_rows > 0) { if ($num_rows > 0) {
@@ -331,14 +329,14 @@ if (isset($_POST['export_credentials_csv'])) {
$f = fopen('php://memory', 'w'); $f = fopen('php://memory', 'w');
//set column headers //set column headers
$fields = array('Name', 'Description', 'Username', 'Password', 'URI'); $fields = array('Name', 'Description', 'Username', 'Password', 'TOTP', 'URI');
fputcsv($f, $fields, $delimiter, $enclosure, $escape); fputcsv($f, $fields, $delimiter, $enclosure, $escape);
//output each row of the data, format line as csv and write to file pointer //output each row of the data, format line as csv and write to file pointer
while($row = mysqli_fetch_assoc($sql)){ while($row = mysqli_fetch_assoc($sql)){
$credential_username = decryptCredentialEntry($row['credential_username']); $credential_username = decryptCredentialEntry($row['credential_username']);
$credential_password = decryptCredentialEntry($row['credential_password']); $credential_password = decryptCredentialEntry($row['credential_password']);
$lineData = array($row['credential_name'], $row['credential_description'], $credential_username, $credential_password, $row['credential_uri']); $lineData = array($row['credential_name'], $row['credential_description'], $credential_username, $credential_password, $row['credential_otp_secret'], $row['credential_uri']);
fputcsv($f, $lineData, $delimiter, $enclosure, $escape); fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
} }
@@ -390,7 +388,7 @@ if (isset($_POST["import_credentials_csv"])) {
//(Else)Check column count //(Else)Check column count
$f = fopen($file_name, "r"); $f = fopen($file_name, "r");
$f_columns = fgetcsv($f, 1000, ","); $f_columns = fgetcsv($f, 1000, ",");
if (!$error & count($f_columns) != 5) { if (!$error & count($f_columns) != 6) {
$error = true; $error = true;
flash_alert("Bad column count.", 'error'); flash_alert("Bad column count.", 'error');
} }
@@ -403,31 +401,40 @@ if (isset($_POST["import_credentials_csv"])) {
$duplicate_count = 0; $duplicate_count = 0;
while(($column = fgetcsv($file, 1000, ",")) !== false){ while(($column = fgetcsv($file, 1000, ",")) !== false){
$duplicate_detect = 0; $duplicate_detect = 0;
// Name
if (isset($column[0])) { if (isset($column[0])) {
$name = sanitizeInput($column[0]); $name = sanitizeInput($column[0]);
if (mysqli_num_rows(mysqli_query($mysqli,"SELECT * FROM credentials WHERE credential_name = '$name' AND credential_client_id = $client_id")) > 0){ if (mysqli_num_rows(mysqli_query($mysqli,"SELECT * FROM credentials WHERE credential_name = '$name' AND credential_client_id = $client_id")) > 0){
$duplicate_detect = 1; $duplicate_detect = 1;
} }
} }
// Desc
if (isset($column[1])) { if (isset($column[1])) {
$description = sanitizeInput($column[1]); $description = sanitizeInput($column[1]);
} }
// User
if (isset($column[2])) { if (isset($column[2])) {
$username = sanitizeInput(encryptCredentialEntry($column[2])); $username = sanitizeInput(encryptCredentialEntry($column[2]));
} }
// Pass
if (isset($column[3])) { if (isset($column[3])) {
$password = sanitizeInput(encryptCredentialEntry($column[3])); $password = sanitizeInput(encryptCredentialEntry($column[3]));
} }
// OTP
if (isset($column[4])) { if (isset($column[4])) {
$uri = sanitizeInput($column[4]); $totp = sanitizeInput($column[4]);
}
// URL
if (isset($column[4])) {
$uri = sanitizeInput($column[5]);
} }
// Check if duplicate was detected // Check if duplicate was detected
if ($duplicate_detect == 0){ if ($duplicate_detect == 0){
//Add //Add
mysqli_query($mysqli,"INSERT INTO credentials SET credential_name = '$name', credential_description = '$description', credential_uri = '$uri', credential_username = '$username', credential_password = '$password', credential_client_id = $client_id"); mysqli_query($mysqli,"INSERT INTO credentials SET credential_name = '$name', credential_description = '$description', credential_uri = '$uri', credential_username = '$username', credential_password = '$password', credential_otp_secret = '$totp', credential_client_id = $client_id");
$row_count = $row_count + 1; $row_count = $row_count + 1;
}else{ } else {
$duplicate_count = $duplicate_count + 1; $duplicate_count = $duplicate_count + 1;
} }
} }
@@ -455,7 +462,7 @@ if (isset($_GET['download_credentials_csv_template'])) {
$f = fopen('php://memory', 'w'); $f = fopen('php://memory', 'w');
//set column headers //set column headers
$fields = array('Name', 'Description', 'Username', 'Password', 'URI'); $fields = array('Name', 'Description', 'Username', 'Password', 'TOTP', 'URI');
fputcsv($f, $fields, $delimiter); fputcsv($f, $fields, $delimiter);
//move back to beginning of file //move back to beginning of file

View File

@@ -633,7 +633,15 @@ if (isset($_GET['delete_document'])) {
flash_alert("Document <strong>$document_name</strong> deleted and all versions", 'error'); flash_alert("Document <strong>$document_name</strong> deleted and all versions", 'error');
// Determine redirect behavior
// If there's a "from" parameter, we can use it to decide where to go
if (isset($_GET['from']) && $_GET['from'] === 'document_details') {
// User deleted from document_details.php
redirect("documents.php?client_id=$client_id");
} else {
// Default behavior — redirect back to previous page
redirect(); redirect();
}
} }

View File

@@ -336,83 +336,3 @@ if (isset($_POST['export_expenses_csv'])) {
exit; exit;
} }
if (isset($_POST['create_recurring_expense'])) {
$frequency = intval($_POST['frequency']);
$day = intval($_POST['day']);
$month = intval($_POST['month']);
$amount = floatval(str_replace(',', '', $_POST['amount']));
$account = intval($_POST['account']);
$vendor = intval($_POST['vendor']);
$client_id = intval($_POST['client']);
$category = intval($_POST['category']);
$description = sanitizeInput($_POST['description']);
$reference = sanitizeInput($_POST['reference']);
$year = date('Y');
if (strtotime("$year-$month-$day") < time()) {
$year++;
}
$start_date = "$year-$month-$day";
mysqli_query($mysqli,"INSERT INTO recurring_expenses SET recurring_expense_frequency = $frequency, recurring_expense_day = $day, recurring_expense_month = $month, recurring_expense_next_date = '$start_date', recurring_expense_description = '$description', recurring_expense_reference = '$reference', recurring_expense_amount = $amount, recurring_expense_currency_code = '$session_company_currency', recurring_expense_vendor_id = $vendor, recurring_expense_client_id = $client_id, recurring_expense_category_id = $category, recurring_expense_account_id = $account");
$recurring_expense_id = mysqli_insert_id($mysqli);
logAction("Recurring Expense", "Create", "$session_name created recurring expense $description", $client_id, $recurring_expense_id);
flash_alert("Recurring Expense created");
redirect();
}
if (isset($_POST['edit_recurring_expense'])) {
$recurring_expense_id = intval($_POST['recurring_expense_id']);
$frequency = intval($_POST['frequency']);
$day = intval($_POST['day']);
$month = intval($_POST['month']);
$amount = floatval(str_replace(',', '', $_POST['amount']));
$account = intval($_POST['account']);
$vendor = intval($_POST['vendor']);
$client_id = intval($_POST['client']);
$category = intval($_POST['category']);
$description = sanitizeInput($_POST['description']);
$reference = sanitizeInput($_POST['reference']);
$year = date('Y');
if (strtotime("$year-$month-$day") < time()) {
$year++;
}
$start_date = "$year-$month-$day";
mysqli_query($mysqli,"UPDATE recurring_expenses SET recurring_expense_frequency = $frequency, recurring_expense_day = $day, recurring_expense_month = $month, recurring_expense_next_date = '$start_date', recurring_expense_description = '$description', recurring_expense_reference = '$reference', recurring_expense_amount = $amount, recurring_expense_currency_code = '$session_company_currency', recurring_expense_vendor_id = $vendor, recurring_expense_client_id = $client_id, recurring_expense_category_id = $category, recurring_expense_account_id = $account WHERE recurring_expense_id = $recurring_expense_id");
logAction("Recurring Expense", "Edit", "$session_name edited recurring expense $description", $client_id, $recurring_expense_id);
flash_alert("Recurring Expense edited");
redirect();
}
if (isset($_GET['delete_recurring_expense'])) {
$recurring_expense_id = intval($_GET['delete_recurring_expense']);
// Get Recurring Expense Details for Logging
$sql = mysqli_query($mysqli,"SELECT recurring_expense_description, recurring_expense_client_id FROM recurring_expenses WHERE recurring_expense_id = $recurring_expense_id");
$row = mysqli_fetch_array($sql);
$recurring_expense_description = sanitizeInput($row['recurring_expense_description']);
$client_id = intval($row['recurring_expense_client_id']);
mysqli_query($mysqli,"DELETE FROM recurring_expenses WHERE recurring_expense_id = $recurring_expense_id");
logAction("Recurring Expense", "Delete", "$session_name deleted recurring expense $recurring_expense_description", $client_id);
flash_alert("Recurring Expense deleted", 'error');
redirect();
}

File diff suppressed because it is too large Load Diff

901
agent/post/payment.php Normal file
View File

@@ -0,0 +1,901 @@
<?php
/*
* ITFlow - GET/POST request handler for credits & payments
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_payment'])) {
enforceUserPermission('module_sales', 2);
enforceUserPermission('module_financial', 2);
$invoice_id = intval($_POST['invoice_id']);
$balance = floatval($_POST['balance']);
$date = sanitizeInput($_POST['date']);
$amount = floatval($_POST['amount']);
$account = intval($_POST['account']);
$currency_code = sanitizeInput($_POST['currency_code']);
$payment_method = sanitizeInput($_POST['payment_method']);
$reference = sanitizeInput($_POST['reference']);
$email_receipt = intval($_POST['email_receipt']);
//Check to see if amount entered is greater than the balance of the invoice
if ($amount > $balance) {
flash_alert("Payment can not be more than the balance", 'error');
redirect();
} else {
mysqli_query($mysqli,"INSERT INTO payments SET payment_date = '$date', payment_amount = $amount, payment_currency_code = '$currency_code', payment_account_id = $account, payment_method = '$payment_method', payment_reference = '$reference', payment_invoice_id = $invoice_id");
// Get Payment ID for reference
$payment_id = mysqli_insert_id($mysqli);
//Add up all the payments for the invoice and get the total amount paid to the invoice
$sql_total_payments_amount = mysqli_query($mysqli,"SELECT SUM(payment_amount) AS payments_amount FROM payments WHERE payment_invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql_total_payments_amount);
$total_payments_amount = floatval($row['payments_amount']);
//Get the invoice total
$sql = mysqli_query($mysqli,"SELECT * FROM invoices
LEFT JOIN clients ON invoice_client_id = client_id
LEFT JOIN contacts ON clients.client_id = contacts.contact_client_id AND contact_primary = 1
WHERE invoice_id = $invoice_id"
);
$row = mysqli_fetch_array($sql);
$invoice_amount = floatval($row['invoice_amount']);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_url_key = sanitizeInput($row['invoice_url_key']);
$invoice_currency_code = sanitizeInput($row['invoice_currency_code']);
$client_id = intval($row['client_id']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$contact_phone = sanitizeInput(formatPhoneNumber($row['contact_phone'], $row['contact_phone_country_code']));
$contact_extension = preg_replace("/[^0-9]/", '',$row['contact_extension']);
$contact_mobile = sanitizeInput(formatPhoneNumber($row['contact_mobile'], $row['contact_mobile_country_code']));
$sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_country = sanitizeInput($row['company_country']);
$company_address = sanitizeInput($row['company_address']);
$company_city = sanitizeInput($row['company_city']);
$company_state = sanitizeInput($row['company_state']);
$company_zip = sanitizeInput($row['company_zip']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
$company_email = sanitizeInput($row['company_email']);
$company_website = sanitizeInput($row['company_website']);
$company_logo = sanitizeInput($row['company_logo']);
// Sanitize Config vars from get_settings.php
$config_invoice_from_name = sanitizeInput($config_invoice_from_name);
$config_invoice_from_email = sanitizeInput($config_invoice_from_email);
//Calculate the Invoice balance
$invoice_balance = $invoice_amount - $total_payments_amount;
$email_data = [];
//Determine if invoice has been paid then set the status accordingly
if ($invoice_balance == 0) {
$invoice_status = "Paid";
if ($email_receipt == 1) {
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>We have received your payment in full for the amount of " . numfmt_format_currency($currency_format, $amount, $invoice_currency_code) . " for invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount Paid: " . numfmt_format_currency($currency_format, $amount, $invoice_currency_code) . "<br>Payment Method: $payment_method<br>Payment Reference: $reference<br><br>Thank you for your business!<br><br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
// Queue Mail
$email = [
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body
];
$email_data[] = $email;
// Add email to queue
if (!empty($email)) {
addToMailQueue($email_data);
}
// Get Email ID for reference
$email_id = mysqli_insert_id($mysqli);
// Email Logging
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Payment Receipt sent to mail queue ID: $email_id!', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Payment receipt for invoice $invoice_prefix$invoice_number queued to $contact_email Email ID: $email_id", $client_id, $invoice_id);
}
} else {
$invoice_status = "Partial";
if ($email_receipt == 1) {
$subject = "Partial Payment Received - Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>We have received partial payment in the amount of " . numfmt_format_currency($currency_format, $amount, $invoice_currency_code) . " and it has been applied to invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount Paid: " . numfmt_format_currency($currency_format, $amount, $invoice_currency_code) . "<br>Payment Method: $payment_method<br>Payment Reference: $reference<br>Invoice Balance: " . numfmt_format_currency($currency_format, $invoice_balance, $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>~<br>$company_name - Billing<br>$config_invoice_from_email<br>$company_phone";
// Queue Mail
$email = [
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body
];
$email_data[] = $email;
// Add email to queue
if (!empty($email)) {
addToMailQueue($email_data);
}
// Get Email ID for reference
$email_id = mysqli_insert_id($mysqli);
// Email Logging
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Payment Receipt sent to mail queue ID: $email_id!', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Payment receipt for invoice $invoice_prefix$invoice_number queued to $contact_email Email ID: $email_id", $client_id, $invoice_id);
}
}
//Update Invoice Status
mysqli_query($mysqli,"UPDATE invoices SET invoice_status = '$invoice_status' WHERE invoice_id = $invoice_id");
//Add Payment to History
mysqli_query($mysqli,"INSERT INTO history SET history_status = '$invoice_status', history_description = 'Payment added', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Payment amount of " . numfmt_format_currency($currency_format, $amount, $invoice_currency_code) . " added to invoice $invoice_prefix$invoice_number", $client_id, $invoice_id);
customAction('invoice_pay', $invoice_id);
flash_alert("Payment amount <strong>" . numfmt_format_currency($currency_format, $amount, $invoice_currency_code) . "</strong> added");
redirect();
}
}
/*
Apply Credit Not ready for use 2025-08-27 - JQ
if (isset($_POST['apply_credit'])) {
enforceUserPermission('module_sales', 2);
enforceUserPermission('module_financial', 2);
$invoice_id = intval($_POST['invoice_id']);
$credit_amount_applied = floatval($_POST['credit_amount_applied']);
$sql = mysqli_query($mysqli, "SELECT * FROM invoices LEFT JOIN clients ON invoice_client_id = client_id WHERE invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_status = sanitizeInput($row['invoice_status']);
$invoice_credit_amount = floatval($row['invoice_credit_amount']);
$invoice_amount = floatval('invoice_amount');
$client_id = intval($row['invoice_client_id']);
// Get Credit Balance
$sql_credit_balance = mysqli_query($mysqli, "SELECT SUM(credit_amount) AS credit_balance FROM credits WHERE credit_client_id = $client_id");
$row = mysqli_fetch_array($sql_credit_balance);
$credit_balance = floatval($row['credit_balance']);
// Get Invoice Balance
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql_amount_paid);
$amount_paid = floatval($row['amount_paid']);
$invoice_balance = $invoice_amount - $amount_paid;
// Get Credit Tally applied to invoice
$sql_credit_tally = mysqli_query($mysqli, "SELECT SUM(credit_tally) AS credit_balance FROM credits WHERE credit_invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql_credit_tally);
$credit_tally = floatval($row['credit_tally']);
// Check to see if amount entered is greater than the balance of the invoice
if ($credit_amount_applied > $invoice_balance) {
flash_alert("Credit can not be more than the balance", 'alert');
redirect();
}
// Check to see if amount entered is greater than the credit balance
if ($credit_amount_applied > $credit_balance) {
flash_alert("Credit can not be more than the available credit", 'alert');
redirect();
}
// Insert a new credit usage record linked to the invoice
mysqli_query($mysqli, "
INSERT INTO credits SET
credit_amount = -$amount,
credit_type = 'usage',
credit_created_by = $session_user_id,
credit_client_id = $client_id,
credit_invoice_id = $invoice_id
");
$new_invoice_amount = $invoice_amount - $credit_amount_applied;
// Calculate updated invoice credit sum
$result = mysqli_query($mysqli, "
SELECT SUM(credit_amount) AS credit_total
FROM credits
WHERE credit_invoice_id = $invoice_id
");
$total_credit_applied = floatval(mysqli_fetch_assoc($result)['credit_total']);
// Get invoice amount
$invoice_amount = floatval(getFieldByID('invoices', $invoice_id, 'invoice_amount'));
// Determine new status
$invoice_due = $invoice_amount + $total_credit_applied;
$invoice_status = ($invoice_due <= 0) ? 'Paid' : 'Partial';
// Update the invoice credit amount
mysqli_query($mysqli, "
UPDATE invoices
SET invoice_credit_amount = $total_credit_applied
WHERE invoice_id = $invoice_id
");
// Update invoice status only (not invoice_credit_amount)
mysqli_query($mysqli, "UPDATE invoices SET invoice_status = '$invoice_status' WHERE invoice_id = $invoice_id");
// Log credit application in history
mysqli_query($mysqli, "
INSERT INTO history SET
history_status = '$invoice_status',
history_description = 'Credit applied',
history_invoice_id = $invoice_id
");
logAction("Invoice", "Payment", "Credit " . numfmt_format_currency($currency_format, $amount, $session_company_currency) . " applied to invoice $invoice_prefix$invoice_number", $client_id, $invoice_id);
customAction('invoice_pay', $invoice_id);
flash_alert("Credit amount <strong>" . numfmt_format_currency($currency_format, $amount, $session_company_currency) . "</strong> applied");
redirect();
}
*/
if (isset($_POST['add_payment_stripe'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_sales', 2);
enforceUserPermission('module_financial', 2);
$invoice_id = intval($_POST['invoice_id']);
$saved_payment_id = intval($_POST['saved_payment_id']);
// Get invoice details
$sql = mysqli_query($mysqli,"SELECT * FROM invoices
LEFT JOIN clients ON invoice_client_id = client_id
LEFT JOIN contacts ON client_id = contact_client_id AND contact_primary = 1
WHERE invoice_id = $invoice_id"
);
$row = mysqli_fetch_array($sql);
$invoice_number = intval($row['invoice_number']);
$invoice_status = sanitizeInput($row['invoice_status']);
$invoice_amount = floatval($row['invoice_amount']);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_url_key = sanitizeInput($row['invoice_url_key']);
$invoice_currency_code = sanitizeInput($row['invoice_currency_code']);
$client_id = intval($row['client_id']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$contact_phone = sanitizeInput(formatPhoneNumber($row['contact_phone'], $row['contact_phone_country_code']));
$contact_extension = preg_replace("/[^0-9]/", '',$row['contact_extension']);
$contact_mobile = sanitizeInput(formatPhoneNumber($row['contact_mobile'], $row['contact_mobile_country_code']));
// Get ITFlow company details
$sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_country = sanitizeInput($row['company_country']);
$company_address = sanitizeInput($row['company_address']);
$company_city = sanitizeInput($row['company_city']);
$company_state = sanitizeInput($row['company_state']);
$company_zip = sanitizeInput($row['company_zip']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
$company_email = sanitizeInput($row['company_email']);
$company_website = sanitizeInput($row['company_website']);
// Sanitize Config vars from get_settings.php
$config_invoice_from_name = sanitizeInput($config_invoice_from_name);
$config_invoice_from_email = sanitizeInput($config_invoice_from_email);
// Get Client Payment Details
$sql = mysqli_query($mysqli, "SELECT * FROM client_saved_payment_methods LEFT JOIN payment_providers ON saved_payment_provider_id = payment_provider_id LEFT JOIN client_payment_provider ON saved_payment_client_id = client_id WHERE saved_payment_id = $saved_payment_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$public_key = sanitizeInput($row['payment_provider_public_key']);
$private_key = sanitizeInput($row['payment_provider_private_key']);
$account_id = intval($row['payment_provider_account']);
$expense_category_id = intval($row['payment_provider_expense_category']);
$expense_vendor_id = intval($row['payment_provider_expense_vendor']);
$expense_percentage_fee = floatval($row['payment_provider_expense_percentage_fee']);
$expense_flat_fee = floatval($row['payment_provider_expense_flat_fee']);
$payment_provider_client = sanitizeInput($row['payment_provider_client']);
$saved_payment_method = sanitizeInput($row['saved_payment_provider_method']);
$saved_payment_description = sanitizeInput($row['saved_payment_description']);
// Sanity checks
if (!$payment_provider_client || !$saved_payment_method) {
flash_alert("Stripe not enabled or no client card saved", 'error');
redirect();
} elseif ($invoice_status !== 'Sent' && $invoice_status !== 'Viewed') {
flash_alert("Invalid invoice state (draft/partial/paid/not billable)", 'error');
redirect();
} elseif ($invoice_amount == 0) {
flash_alert("Invalid invoice amount", 'error');
redirect();
}
// Initialize Stripe
require_once __DIR__ . '/../../plugins/stripe-php/init.php';
$stripe = new \Stripe\StripeClient($private_key);
$balance_to_pay = round($invoice_amount, 2);
$pi_description = "ITFlow: $client_name payment of $invoice_currency_code $balance_to_pay for $invoice_prefix$invoice_number";
// Create a payment intent
try {
$payment_intent = $stripe->paymentIntents->create([
'amount' => intval($balance_to_pay * 100), // Times by 100 as Stripe expects values in cents
'currency' => $invoice_currency_code,
'customer' => $payment_provider_client,
'payment_method' => $saved_payment_method,
'off_session' => true,
'confirm' => true,
'description' => $pi_description,
'metadata' => [
'itflow_client_id' => $client_id,
'itflow_client_name' => $client_name,
'itflow_invoice_number' => $invoice_prefix . $invoice_number,
'itflow_invoice_id' => $invoice_id,
]
]);
// Get details from PI
$pi_id = sanitizeInput($payment_intent->id);
$pi_date = date('Y-m-d', $payment_intent->created);
$pi_amount_paid = floatval(($payment_intent->amount_received / 100));
$pi_currency = strtoupper(sanitizeInput($payment_intent->currency));
$pi_livemode = $payment_intent->livemode;
} catch (Exception $e) {
$error = $e->getMessage();
error_log("Stripe payment error - encountered exception during payment intent for invoice ID $invoice_id / $invoice_prefix$invoice_number: $error");
logApp("Stripe", "error", "Exception during PI for invoice ID $invoice_id: $error");
}
if ($payment_intent->status == "succeeded" && intval($balance_to_pay) == intval($pi_amount_paid)) {
// Update Invoice Status
mysqli_query($mysqli, "UPDATE invoices SET invoice_status = 'Paid' WHERE invoice_id = $invoice_id");
// Add Payment to History
mysqli_query($mysqli, "INSERT INTO payments SET payment_date = '$pi_date', payment_amount = $pi_amount_paid, payment_currency_code = '$pi_currency', payment_account_id = $account_id, payment_method = 'Stripe', payment_reference = 'Stripe - $pi_id', payment_invoice_id = $invoice_id");
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Paid', history_description = 'Online Payment added (agent)', history_invoice_id = $invoice_id");
// Email receipt
if (!empty($config_smtp_host)) {
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>We have received online payment for the amount of " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . " for invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount Paid: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
// Queue Mail
$data = [
[
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body,
]
];
// Email the internal notification address too
if (!empty($config_invoice_paid_notification_email)) {
$subject = "Payment Received - $client_name - Invoice $invoice_prefix$invoice_number";
$body = "Hello, <br><br>This is a notification that an invoice has been paid in ITFlow. Below is a copy of the receipt sent to the client:-<br><br>--------<br><br>Hello $contact_name,<br><br>We have received online payment for the amount of " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . " for invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount Paid: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
$data[] = [
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $config_invoice_paid_notification_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body,
];
}
$mail = addToMailQueue($data);
// Email Logging
$email_id = mysqli_insert_id($mysqli);
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Payment Receipt sent to mail queue ID: $email_id!', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Payment receipt for invoice $invoice_prefix$invoice_number queued to $contact_email Email ID: $email_id", $client_id, $invoice_id);
}
// Log info
$extended_log_desc = '';
if (!$pi_livemode) {
$extended_log_desc = '(DEV MODE)';
}
// Create Stripe payment gateway fee as an expense (if configured)
if ($expense_vendor_id > 0 && $expense_category_id > 0) {
$gateway_fee = round($invoice_amount * $expense_percentage_fee + $expense_flat_fee, 2);
mysqli_query($mysqli,"INSERT INTO expenses SET expense_date = '$pi_date', expense_amount = $gateway_fee, expense_currency_code = '$invoice_currency_code', expense_account_id = $account_id, expense_vendor_id = $expense_vendor_id, expense_client_id = $client_id, expense_category_id = $expense_category_id, expense_description = 'Stripe Transaction for Invoice $invoice_prefix$invoice_number In the Amount of $balance_to_pay', expense_reference = 'Stripe - $pi_id $extended_log_desc'");
}
// Notify/log
appNotify("Invoice Paid", "Invoice $invoice_prefix$invoice_number automatically paid", "/agent/invoice.php?invoice_id=$invoice_id", $client_id);
logAction("Invoice", "Payment", "$session_name initiated Stripe payment amount of " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . " added to invoice $invoice_prefix$invoice_number - $pi_id $extended_log_desc", $client_id, $invoice_id);
customAction('invoice_pay', $invoice_id);
flash_alert("Payment amount <strong>" . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "</strong> added");
redirect();
} else {
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Payment failed', history_description = 'Stripe pay failed due to payment error', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Failed online payment amount of invoice $invoice_prefix$invoice_number due to Stripe payment error", $client_id, $invoice_id);
flash_alert("Payment failed", 'error');
redirect();
}
}
/*
if (isset($_GET['add_payment_stripe'])) {
validateCSRFToken($_GET['csrf_token']);
enforceUserPermission('module_sales', 2);
enforceUserPermission('module_financial', 2);
$invoice_id = intval($_GET['invoice_id']);
// Get invoice details
$sql = mysqli_query($mysqli,"SELECT * FROM invoices
LEFT JOIN clients ON invoice_client_id = client_id
LEFT JOIN contacts ON clients.client_id = contacts.contact_client_id AND contact_primary = 1
WHERE invoice_id = $invoice_id"
);
$row = mysqli_fetch_array($sql);
$invoice_number = intval($row['invoice_number']);
$invoice_status = sanitizeInput($row['invoice_status']);
$invoice_amount = floatval($row['invoice_amount']);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_url_key = sanitizeInput($row['invoice_url_key']);
$invoice_currency_code = sanitizeInput($row['invoice_currency_code']);
$client_id = intval($row['client_id']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$contact_phone = sanitizeInput(formatPhoneNumber($row['contact_phone'], $row['contact_phone_country_code']));
$contact_extension = preg_replace("/[^0-9]/", '',$row['contact_extension']);
$contact_mobile = sanitizeInput(formatPhoneNumber($row['contact_mobile'], $row['contact_mobile_country_code']));
// Get ITFlow company details
$sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_country = sanitizeInput($row['company_country']);
$company_address = sanitizeInput($row['company_address']);
$company_city = sanitizeInput($row['company_city']);
$company_state = sanitizeInput($row['company_state']);
$company_zip = sanitizeInput($row['company_zip']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
$company_email = sanitizeInput($row['company_email']);
$company_website = sanitizeInput($row['company_website']);
// Sanitize Config vars from get_settings.php
$config_invoice_from_name = sanitizeInput($config_invoice_from_name);
$config_invoice_from_email = sanitizeInput($config_invoice_from_email);
// Get Client Stripe details
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM client_stripe WHERE client_id = $client_id LIMIT 1"));
$stripe_id = sanitizeInput($stripe_client_details['stripe_id']);
$stripe_pm = sanitizeInput($stripe_client_details['stripe_pm']);
// Sanity checks
if (!$config_stripe_enable || !$stripe_id || !$stripe_pm) {
flash_alert("Stripe not enabled or no client card saved", 'error');
redirect();
} elseif ($invoice_status !== 'Sent' && $invoice_status !== 'Viewed') {
flash_alert("Invalid invoice state (draft/partial/paid/not billable)", 'error');
redirect();
} elseif ($invoice_amount == 0) {
flash_alert("Invalid invoice amount", 'error');
redirect();
}
// Initialize Stripe
require_once __DIR__ . '/../plugins/stripe-php/init.php';
$stripe = new \Stripe\StripeClient($config_stripe_secret);
$balance_to_pay = round($invoice_amount, 2);
$pi_description = "ITFlow: $client_name payment of $invoice_currency_code $balance_to_pay for $invoice_prefix$invoice_number";
// Create a payment intent
try {
$payment_intent = $stripe->paymentIntents->create([
'amount' => intval($balance_to_pay * 100), // Times by 100 as Stripe expects values in cents
'currency' => $invoice_currency_code,
'customer' => $stripe_id,
'payment_method' => $stripe_pm,
'off_session' => true,
'confirm' => true,
'description' => $pi_description,
'metadata' => [
'itflow_client_id' => $client_id,
'itflow_client_name' => $client_name,
'itflow_invoice_number' => $invoice_prefix . $invoice_number,
'itflow_invoice_id' => $invoice_id,
]
]);
// Get details from PI
$pi_id = sanitizeInput($payment_intent->id);
$pi_date = date('Y-m-d', $payment_intent->created);
$pi_amount_paid = floatval(($payment_intent->amount_received / 100));
$pi_currency = strtoupper(sanitizeInput($payment_intent->currency));
$pi_livemode = $payment_intent->livemode;
} catch (Exception $e) {
$error = $e->getMessage();
error_log("Stripe payment error - encountered exception during payment intent for invoice ID $invoice_id / $invoice_prefix$invoice_number: $error");
logApp("Stripe", "error", "Exception during PI for invoice ID $invoice_id: $error");
}
if ($payment_intent->status == "succeeded" && intval($balance_to_pay) == intval($pi_amount_paid)) {
// Update Invoice Status
mysqli_query($mysqli, "UPDATE invoices SET invoice_status = 'Paid' WHERE invoice_id = $invoice_id");
// Add Payment to History
mysqli_query($mysqli, "INSERT INTO payments SET payment_date = '$pi_date', payment_amount = $pi_amount_paid, payment_currency_code = '$pi_currency', payment_account_id = $config_stripe_account, payment_method = 'Stripe', payment_reference = 'Stripe - $pi_id', payment_invoice_id = $invoice_id");
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Paid', history_description = 'Online Payment added (agent)', history_invoice_id = $invoice_id");
// Email receipt
if (!empty($config_smtp_host)) {
$subject = "Payment Received - Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>We have received online payment for the amount of " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . " for invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount Paid: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
// Queue Mail
$data = [
[
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body,
]
];
// Email the internal notification address too
if (!empty($config_invoice_paid_notification_email)) {
$subject = "Payment Received - $client_name - Invoice $invoice_prefix$invoice_number";
$body = "Hello, <br><br>This is a notification that an invoice has been paid in ITFlow. Below is a copy of the receipt sent to the client:-<br><br>--------<br><br>Hello $contact_name,<br><br>We have received online payment for the amount of " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . " for invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a>. Please keep this email as a receipt for your records.<br><br>Amount Paid: " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "<br><br>Thank you for your business!<br><br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
$data[] = [
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $config_invoice_paid_notification_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body,
];
}
$mail = addToMailQueue($data);
// Email Logging
$email_id = mysqli_insert_id($mysqli);
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Payment Receipt sent to mail queue ID: $email_id!', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Payment receipt for invoice $invoice_prefix$invoice_number queued to $contact_email Email ID: $email_id", $client_id, $invoice_id);
}
// Log info
$extended_log_desc = '';
if (!$pi_livemode) {
$extended_log_desc = '(DEV MODE)';
}
// Create Stripe payment gateway fee as an expense (if configured)
if ($config_stripe_expense_vendor > 0 && $config_stripe_expense_category > 0) {
$gateway_fee = round($invoice_amount * $config_stripe_percentage_fee + $config_stripe_flat_fee, 2);
mysqli_query($mysqli,"INSERT INTO expenses SET expense_date = '$pi_date', expense_amount = $gateway_fee, expense_currency_code = '$invoice_currency_code', expense_account_id = $config_stripe_account, expense_vendor_id = $config_stripe_expense_vendor, expense_client_id = $client_id, expense_category_id = $config_stripe_expense_category, expense_description = 'Stripe Transaction for Invoice $invoice_prefix$invoice_number In the Amount of $balance_to_pay', expense_reference = 'Stripe - $pi_id $extended_log_desc'");
}
// Notify/log
appNotify("Invoice Paid", "Invoice $invoice_prefix$invoice_number automatically paid", "invoice.php?invoice_id=$invoice_id", $client_id);
logAction("Invoice", "Payment", "$session_name initiated Stripe payment amount of " . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . " added to invoice $invoice_prefix$invoice_number - $pi_id $extended_log_desc", $client_id, $invoice_id);
customAction('invoice_pay', $invoice_id);
flash_alert("Payment amount <strong>" . numfmt_format_currency($currency_format, $invoice_amount, $invoice_currency_code) . "</strong> added");
redirect();
} else {
mysqli_query($mysqli, "INSERT INTO history SET history_status = 'Payment failed', history_description = 'Stripe pay failed due to payment error', history_invoice_id = $invoice_id");
logAction("Invoice", "Payment", "Failed online payment amount of invoice $invoice_prefix$invoice_number due to Stripe payment error", $client_id, $invoice_id);
flash_alert("Payment failed", 'error');
redirect();
}
}
*/
if (isset($_POST['add_bulk_payment'])) {
enforceUserPermission('module_sales', 2);
enforceUserPermission('module_financial', 2);
$client_id = intval($_POST['client_id']);
$date = sanitizeInput($_POST['date']);
$bulk_payment_amount = floatval($_POST['amount']);
$bulk_payment_amount_static = floatval($_POST['amount']);
$total_account_balance = floatval($_POST['balance']);
$account = intval($_POST['account']);
$currency_code = sanitizeInput($_POST['currency_code']);
$payment_method = sanitizeInput($_POST['payment_method']);
$reference = sanitizeInput($_POST['reference']);
$email_receipt = intval($_POST['email_receipt']);
// Check if bulk_payment_amount exceeds total_account_balance
if ($bulk_payment_amount > $total_account_balance) {
flash_alert("Payment exceeds Client Balance.", 'error');
redirect();
}
// Get Invoices
$sql_invoices = "SELECT * FROM invoices
WHERE invoice_status != 'Draft'
AND invoice_status != 'Paid'
AND invoice_status != 'Cancelled'
AND invoice_client_id = $client_id
ORDER BY invoice_number ASC";
$result_invoices = mysqli_query($mysqli, $sql_invoices);
// Loop Through Each Invoice
while ($row = mysqli_fetch_array($result_invoices)) {
$invoice_id = intval($row['invoice_id']);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_amount = floatval($row['invoice_amount']);
$invoice_url_key = sanitizeInput($row['invoice_url_key']);
$invoice_balance_query = "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id";
$result_amount_paid = mysqli_query($mysqli, $invoice_balance_query);
$row_amount_paid = mysqli_fetch_array($result_amount_paid);
$amount_paid = floatval($row_amount_paid['amount_paid']);
$invoice_balance = $invoice_amount - $amount_paid;
if ($bulk_payment_amount <= 0) {
break; // Exit the loop if no payment amount is left
}
if ($bulk_payment_amount >= $invoice_balance) {
$payment_amount = $invoice_balance;
$invoice_status = "Paid";
} else {
$payment_amount = $bulk_payment_amount;
$invoice_status = "Partial";
}
// Subtract the payment amount from the bulk payment amount
$bulk_payment_amount -= $payment_amount;
// Get Invoice Remain Balance
$remaining_invoice_balance = $invoice_balance - $payment_amount;
// Add Payment
$payment_query = "INSERT INTO payments (payment_date, payment_amount, payment_currency_code, payment_account_id, payment_method, payment_reference, payment_invoice_id) VALUES ('{$date}', {$payment_amount}, '{$currency_code}', {$account}, '{$payment_method}', '{$reference}', {$invoice_id})";
mysqli_query($mysqli, $payment_query);
$payment_id = mysqli_insert_id($mysqli);
// Update Invoice Status
$update_invoice_query = "UPDATE invoices SET invoice_status = '{$invoice_status}' WHERE invoice_id = {$invoice_id}";
mysqli_query($mysqli, $update_invoice_query);
// Add Payment to History
$history_description = "Payment added";
$add_history_query = "INSERT INTO history (history_status, history_description, history_invoice_id) VALUES ('{$invoice_status}', '{$history_description}', {$invoice_id})";
mysqli_query($mysqli, $add_history_query);
// Add to Email Body Invoice Portion
$email_body_invoices .= "<br>Invoice <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$invoice_id&url_key=$invoice_url_key\'>$invoice_prefix$invoice_number</a> - Outstanding Amount: " . numfmt_format_currency($currency_format, $invoice_balance, $currency_code) . " - Payment Applied: " . numfmt_format_currency($currency_format, $payment_amount, $currency_code) . " - New Balance: " . numfmt_format_currency($currency_format, $remaining_invoice_balance, $currency_code);
customAction('invoice_pay', $invoice_id);
} // End Invoice Loop
// Send Email
if ($email_receipt == 1) {
// Get Client / Contact Info
$sql_client = mysqli_query($mysqli,"SELECT * FROM clients
LEFT JOIN contacts ON clients.client_id = contacts.contact_client_id
AND contact_primary = 1
WHERE client_id = $client_id"
);
$row = mysqli_fetch_array($sql_client);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$sql_company = mysqli_query($mysqli,"SELECT company_name, company_phone, company_phone_country_code FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql_company);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// Sanitize Config vars from get_settings.php
$config_invoice_from_name = sanitizeInput($config_invoice_from_name);
$config_invoice_from_email = sanitizeInput($config_invoice_from_email);
$subject = "Payment Received - Multiple Invoices";
$body = "Hello $contact_name,<br><br>Thank you for your payment of " . numfmt_format_currency($currency_format, $bulk_payment_amount_static, $currency_code) . " We\'ve applied your payment to the following invoices, updating their balances accordingly:<br><br>$email_body_invoices<br><br><br>We appreciate your continued business!<br><br>Sincerely,<br>$company_name - Billing<br>$config_invoice_from_email<br>$company_phone";
// Queue Mail
mysqli_query($mysqli, "INSERT INTO email_queue SET email_recipient = '$contact_email', email_recipient_name = '$contact_name', email_from = '$config_invoice_from_email', email_from_name = '$config_invoice_from_name', email_subject = '$subject', email_content = '$body'");
// Get Email ID for reference
$email_id = mysqli_insert_id($mysqli);
// Email Logging
logAction("Payment", "Email", "Bulk Payment receipt for multiple Invoices queued to $contact_email Email ID: $email_id", $client_id);
$alert_message .= "Email receipt queued and ";
} // End Email
logAction("Invoice", "Payment", "Bulk Payment amount of " . numfmt_format_currency($currency_format, $bulk_payment_amount_static, $currency_code) . " applied to multiple invoices", $client_id);
flash_alert("$alert_message Bulk Payment added");
redirect();
}
if (isset($_GET['delete_payment'])) {
enforceUserPermission('module_sales', 2);
enforceUserPermission('module_financial', 2);
$payment_id = intval($_GET['delete_payment']);
$sql = mysqli_query($mysqli,"SELECT * FROM payments WHERE payment_id = $payment_id");
$row = mysqli_fetch_array($sql);
$invoice_id = intval($row['payment_invoice_id']);
$deleted_payment_amount = floatval($row['payment_amount']);
//Add up all the payments for the invoice and get the total amount paid to the invoice
$sql_total_payments_amount = mysqli_query($mysqli,"SELECT SUM(payment_amount) AS total_payments_amount FROM payments WHERE payment_invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql_total_payments_amount);
$total_payments_amount = floatval($row['total_payments_amount']);
// Get the invoice total and details
$sql = mysqli_query($mysqli,"SELECT * FROM invoices WHERE invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$client_id = intval($row['invoice_client_id']);
$invoice_amount = floatval($row['invoice_amount']);
//Calculate the Invoice balance
$invoice_balance = $invoice_amount - $total_payments_amount + $deleted_payment_amount;
//Determine if invoice has been paid
if ($invoice_balance == 0) {
$invoice_status = "Paid";
} else {
$invoice_status = "Partial";
}
//Update Invoice Status
mysqli_query($mysqli,"UPDATE invoices SET invoice_status = '$invoice_status' WHERE invoice_id = $invoice_id");
//Add Payment to History
mysqli_query($mysqli,"INSERT INTO history SET history_status = '$invoice_status', history_description = 'Payment deleted', history_invoice_id = $invoice_id");
mysqli_query($mysqli,"DELETE FROM payments WHERE payment_id = $payment_id");
logAction("Invoice", "Edit", "$session_name deleted Payment on Invoice $invoice_prefix$invoice_number", $client_id, $invoice_id);
flash_alert("Payment deleted", 'error');
if ($config_stripe_enable) {
flash_alert("Payment deleted - Stripe payments must be manually refunded in Stripe", 'error');
}
redirect();
}
if (isset($_POST['export_payments_csv'])) {
if (isset($_POST['client_id'])) {
$client_id = intval($_POST['client_id']);
$client_query = "AND invoice_client_id = $client_id";
$client_name = getFieldById('clients', $client_id, 'client_name');
$file_name_prepend = "$client_name-";
} else {
$client_query = '';
$client_name = '';
$file_name_prepend = "$session_company_name-";
}
$sql = mysqli_query($mysqli,"SELECT * FROM payments, invoices WHERE payment_invoice_id = invoice_id $client_query ORDER BY payment_date ASC");
$num_rows = mysqli_num_rows($sql);
if ($num_rows > 0) {
$delimiter = ",";
$enclosure = '"';
$escape = '\\'; // backslash
$filename = sanitize_filename($file_name_prepend . "Payments-" . date('Y-m-d_H-i-s') . ".csv");
//create a file pointer
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('Payment Date', 'Invoice Date', 'Invoice Number', 'Invoice Amount', 'Payment Amount', 'Payment Method', 'Referrence');
fputcsv($f, $fields, $delimiter, $enclosure, $escape);
//output each row of the data, format line as csv and write to file pointer
while($row = $sql->fetch_assoc()){
$lineData = array($row['payment_date'], $row['invoice_date'], $row['invoice_prefix'] . $row['invoice_number'], $row['invoice_amount'], $row['payment_amount'], $row['payment_method'], $row['payment_reference']);
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
}
//move back to beginning of file
fseek($f, 0);
//set headers to download file rather than displayed
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
//output all remaining data on a file pointer
fpassthru($f);
}
logAction("Payments", "Export", "$session_name exported $num_rows payments to CSV file");
exit;
}

View File

@@ -0,0 +1,87 @@
<?php
/*
* ITFlow - GET/POST request handler for recurring expenses
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['create_recurring_expense'])) {
$frequency = intval($_POST['frequency']);
$day = intval($_POST['day']);
$month = intval($_POST['month']);
$amount = floatval(str_replace(',', '', $_POST['amount']));
$account = intval($_POST['account']);
$vendor = intval($_POST['vendor']);
$client_id = intval($_POST['client']);
$category = intval($_POST['category']);
$description = sanitizeInput($_POST['description']);
$reference = sanitizeInput($_POST['reference']);
$year = date('Y');
if (strtotime("$year-$month-$day") < time()) {
$year++;
}
$start_date = "$year-$month-$day";
mysqli_query($mysqli,"INSERT INTO recurring_expenses SET recurring_expense_frequency = $frequency, recurring_expense_day = $day, recurring_expense_month = $month, recurring_expense_next_date = '$start_date', recurring_expense_description = '$description', recurring_expense_reference = '$reference', recurring_expense_amount = $amount, recurring_expense_currency_code = '$session_company_currency', recurring_expense_vendor_id = $vendor, recurring_expense_client_id = $client_id, recurring_expense_category_id = $category, recurring_expense_account_id = $account");
$recurring_expense_id = mysqli_insert_id($mysqli);
logAction("Recurring Expense", "Create", "$session_name created recurring expense $description", $client_id, $recurring_expense_id);
flash_alert("Recurring Expense created");
redirect();
}
if (isset($_POST['edit_recurring_expense'])) {
$recurring_expense_id = intval($_POST['recurring_expense_id']);
$frequency = intval($_POST['frequency']);
$day = intval($_POST['day']);
$month = intval($_POST['month']);
$amount = floatval(str_replace(',', '', $_POST['amount']));
$account = intval($_POST['account']);
$vendor = intval($_POST['vendor']);
$client_id = intval($_POST['client']);
$category = intval($_POST['category']);
$description = sanitizeInput($_POST['description']);
$reference = sanitizeInput($_POST['reference']);
$year = date('Y');
if (strtotime("$year-$month-$day") < time()) {
$year++;
}
$start_date = "$year-$month-$day";
mysqli_query($mysqli,"UPDATE recurring_expenses SET recurring_expense_frequency = $frequency, recurring_expense_day = $day, recurring_expense_month = $month, recurring_expense_next_date = '$start_date', recurring_expense_description = '$description', recurring_expense_reference = '$reference', recurring_expense_amount = $amount, recurring_expense_currency_code = '$session_company_currency', recurring_expense_vendor_id = $vendor, recurring_expense_client_id = $client_id, recurring_expense_category_id = $category, recurring_expense_account_id = $account WHERE recurring_expense_id = $recurring_expense_id");
logAction("Recurring Expense", "Edit", "$session_name edited recurring expense $description", $client_id, $recurring_expense_id);
flash_alert("Recurring Expense edited");
redirect();
}
if (isset($_GET['delete_recurring_expense'])) {
$recurring_expense_id = intval($_GET['delete_recurring_expense']);
// Get Recurring Expense Details for Logging
$sql = mysqli_query($mysqli,"SELECT recurring_expense_description, recurring_expense_client_id FROM recurring_expenses WHERE recurring_expense_id = $recurring_expense_id");
$row = mysqli_fetch_array($sql);
$recurring_expense_description = sanitizeInput($row['recurring_expense_description']);
$client_id = intval($row['recurring_expense_client_id']);
mysqli_query($mysqli,"DELETE FROM recurring_expenses WHERE recurring_expense_id = $recurring_expense_id");
logAction("Recurring Expense", "Delete", "$session_name deleted recurring expense $recurring_expense_description", $client_id);
flash_alert("Recurring Expense deleted", 'error');
redirect();
}

View File

@@ -0,0 +1,548 @@
<?php
/*
* ITFlow - GET/POST request handler for recurring invoices
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_invoice_recurring'])) {
$invoice_id = intval($_POST['invoice_id']);
$recurring_invoice_frequency = sanitizeInput($_POST['frequency']);
$sql = mysqli_query($mysqli,"SELECT * FROM invoices WHERE invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_date = sanitizeInput($row['invoice_date']);
$invoice_amount = floatval($row['invoice_amount']);
$invoice_currency_code = sanitizeInput($row['invoice_currency_code']);
$invoice_scope = sanitizeInput($row['invoice_scope']);
$invoice_note = sanitizeInput($row['invoice_note']);
$client_id = intval($row['invoice_client_id']);
$category_id = intval($row['invoice_category_id']);
//Get the last Recurring Invoice Number and add 1 for the new Recurring Invoice number
$recurring_invoice_number = $config_recurring_invoice_next_number;
$new_config_recurring_invoice_next_number = $config_recurring_invoice_next_number + 1;
mysqli_query($mysqli,"UPDATE settings SET config_recurring_invoice_next_number = $new_config_recurring_invoice_next_number WHERE company_id = 1");
mysqli_query($mysqli,"INSERT INTO recurring_invoices SET recurring_invoice_prefix = '$config_recurring_invoice_prefix', recurring_invoice_number = $recurring_invoice_number, recurring_invoice_scope = '$invoice_scope', recurring_invoice_frequency = '$recurring_invoice_frequency', recurring_invoice_next_date = DATE_ADD('$invoice_date', INTERVAL 1 $recurring_invoice_frequency), recurring_invoice_status = 1, recurring_invoice_amount = $invoice_amount, recurring_invoice_currency_code = '$invoice_currency_code', recurring_invoice_note = '$invoice_note', recurring_invoice_category_id = $category_id, recurring_invoice_client_id = $client_id");
$recurring_invoice_id = mysqli_insert_id($mysqli);
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Draft', history_description = 'Recurring Invoice Created from INVOICE!', history_recurring_invoice_id = $recurring_invoice_id");
$sql_items = mysqli_query($mysqli,"SELECT * FROM invoice_items WHERE item_invoice_id = $invoice_id");
while($row = mysqli_fetch_array($sql_items)) {
$item_id = intval($row['item_id']);
$item_name = sanitizeInput($row['item_name']);
$item_description = sanitizeInput($row['item_description']);
$item_quantity = floatval($row['item_quantity']);
$item_price = floatval($row['item_price']);
$item_subtotal = floatval($row['item_subtotal']);
$item_tax = floatval($row['item_tax']);
$item_total = floatval($row['item_total']);
$item_order = intval($row['item_order']);
$tax_id = intval($row['item_tax_id']);
mysqli_query($mysqli,"INSERT INTO invoice_items SET item_name = '$item_name', item_description = '$item_description', item_quantity = $item_quantity, item_price = $item_price, item_subtotal = $item_subtotal, item_tax = $item_tax, item_total = $item_total, item_order = $item_order, item_tax_id = $tax_id, item_recurring_invoice_id = $recurring_invoice_id");
}
logAction("Recurring Invoice", "Create", "$session_name created recurring Invoice from Invoice $invoice_prefix$invoice_number", $client_id, $recurring_invoice_id);
flash_alert("Created recurring Invoice from Invoice <strong>$invoice_prefix$invoice_number</strong>");
redirect("recurring_invoice.php?recurring_invoice_id=$recurring_invoice_id");
}
if (isset($_POST['add_recurring_invoice'])) {
$client_id = intval($_POST['client']);
$frequency = sanitizeInput($_POST['frequency']);
$start_date = sanitizeInput($_POST['start_date']);
$category = intval($_POST['category']);
$scope = sanitizeInput($_POST['scope']);
//Get the last Recurring Number and add 1 for the new Recurring number
$recurring_invoice_number = $config_recurring_invoice_next_number;
$new_config_recurring_invoice_next_number = $config_recurring_invoice_next_number + 1;
mysqli_query($mysqli,"UPDATE settings SET config_recurring_invoice_next_number = $new_config_recurring_invoice_next_number WHERE company_id = 1");
mysqli_query($mysqli,"INSERT INTO recurring_invoices SET recurring_invoice_prefix = '$config_recurring_invoice_prefix', recurring_invoice_number = $recurring_invoice_number, recurring_invoice_scope = '$scope', recurring_invoice_frequency = '$frequency', recurring_invoice_next_date = '$start_date', recurring_invoice_category_id = $category, recurring_invoice_status = 1, recurring_invoice_currency_code = '$session_company_currency', recurring_invoice_client_id = $client_id");
$recurring_invoice_id = mysqli_insert_id($mysqli);
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Active', history_description = 'Recurring Invoice created', history_recurring_invoice_id = $recurring_invoice_id");
logAction("Recurring Invoice", "Create", "$session_name created recurring invoice $config_recurring_invoice_prefix$recurring_invoice_number - $scope", $client_id, $recurring_invoice_id);
flash_alert("Recurring Invoice <strong>$config_recurring_invoice_prefix$recurring_invoice_number</strong> created");
redirect("recurring_invoice.php?recurring_invoice_id=$recurring_invoice_id");
}
if (isset($_POST['edit_recurring_invoice'])) {
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
$frequency = sanitizeInput($_POST['frequency']);
$next_date = sanitizeInput($_POST['next_date']);
$category = intval($_POST['category']);
$scope = sanitizeInput($_POST['scope']);
$status = intval($_POST['status']);
$recurring_invoice_discount = floatval($_POST['recurring_invoice_discount']);
// Get Recurring Invoice Details and Client ID for Logging
$sql = mysqli_query($mysqli,"SELECT recurring_invoice_prefix, recurring_invoice_number, recurring_invoice_client_id FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$client_id = intval($row['recurring_invoice_client_id']);
//Calculate new total
$sql = mysqli_query($mysqli,"SELECT * FROM invoice_items WHERE item_recurring_invoice_id = $recurring_invoice_id");
$recurring_invoice_amount = 0;
while($row = mysqli_fetch_array($sql)) {
$item_total = floatval($row['item_total']);
$recurring_invoice_amount = $recurring_invoice_amount + $item_total;
}
$recurring_invoice_amount = $recurring_invoice_amount - $recurring_invoice_discount;
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_scope = '$scope', recurring_invoice_frequency = '$frequency', recurring_invoice_next_date = '$next_date', recurring_invoice_category_id = $category, recurring_invoice_discount_amount = $recurring_invoice_discount, recurring_invoice_amount = $recurring_invoice_amount, recurring_invoice_status = $status WHERE recurring_invoice_id = $recurring_invoice_id");
mysqli_query($mysqli,"INSERT INTO history SET history_status = '$status', history_description = 'Recurring Invoice edited', history_recurring_invoice_id = $recurring_invoice_id");
logAction("Recurring Invoice", "Edit", "$session_name edited recurring invoice $recurring_invoice_prefix$recurring_invoice_number - $scope", $client_id, $recurring_invoice_id);
flash_alert("Recurring Invoice <strong>$recurring_invoice_prefix$recurring_invoice_number</strong> edited");
redirect();
}
if (isset($_GET['delete_recurring_invoice'])) {
$recurring_invoice_id = intval($_GET['delete_recurring_invoice']);
// Get Recurring Invoice Details and Client ID for Logging
$sql = mysqli_query($mysqli,"SELECT recurring_invoice_prefix, recurring_invoice_number, recurring_invoice_scope, recurring_invoice_client_id FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$recurring_invoice_scope = sanitizeInput($row['recurring_invoice_scope']);
$client_id = intval($row['recurring_invoice_client_id']);
mysqli_query($mysqli,"DELETE FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
//Delete Items Associated with the Recurring
$sql = mysqli_query($mysqli,"SELECT * FROM invoice_items WHERE item_recurring_invoice_id = $recurring_invoice_id");
while($row = mysqli_fetch_array($sql)) {
$item_id = intval($row['item_id']);
mysqli_query($mysqli,"DELETE FROM invoice_items WHERE item_id = $item_id");
}
//Delete History Associated with the Invoice
$sql = mysqli_query($mysqli,"SELECT * FROM history WHERE history_recurring_invoice_id = $recurring_invoice_id");
while($row = mysqli_fetch_array($sql)) {
$history_id = intval($row['history_id']);
mysqli_query($mysqli,"DELETE FROM history WHERE history_id = $history_id");
}
logAction("Recurring Invoice", "Delete", "$session_name deleted recurring invoice $recurring_invoice_prefix$recurring_invoice_number - $recurring_invoice_scope", $client_id);
flash_alert("Recurring Invoice <strong>$recurring_invoice_prefix$recurring_invoice_number</strong> deleted", 'error');
redirect();
}
if (isset($_POST['add_recurring_invoice_item'])) {
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
$name = sanitizeInput($_POST['name']);
$description = sanitizeInput($_POST['description']);
$qty = floatval($_POST['qty']);
$price = floatval($_POST['price']);
$tax_id = intval($_POST['tax_id']);
$item_order = intval($_POST['item_order']);
$subtotal = $price * $qty;
if ($tax_id > 0) {
$sql = mysqli_query($mysqli,"SELECT * FROM taxes WHERE tax_id = $tax_id");
$row = mysqli_fetch_array($sql);
$tax_percent = floatval($row['tax_percent']);
$tax_amount = $subtotal * $tax_percent / 100;
} else {
$tax_amount = 0;
}
$total = $subtotal + $tax_amount;
mysqli_query($mysqli,"INSERT INTO invoice_items SET item_name = '$name', item_description = '$description', item_quantity = $qty, item_price = $price, item_subtotal = $subtotal, item_tax = $tax_amount, item_total = $total, item_tax_id = $tax_id, item_order = $item_order, item_recurring_invoice_id = $recurring_invoice_id");
$sql = mysqli_query($mysqli,"SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_discount = floatval($row['recurring_invoice_discount_amount']);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$client_id = intval($row['recurring_invoice_client_id']);
//add up all the items
$sql = mysqli_query($mysqli,"SELECT * FROM invoice_items WHERE item_recurring_invoice_id = $recurring_invoice_id");
$recurring_invoice_amount = 0;
while($row = mysqli_fetch_array($sql)) {
$item_total = floatval($row['item_total']);
$recurring_invoice_amount = $recurring_invoice_amount + $item_total;
}
$recurring_invoice_amount = $recurring_invoice_amount - $recurring_invoice_discount;
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_amount = $recurring_invoice_amount WHERE recurring_invoice_id = $recurring_invoice_id");
logAction("Recurring Invoice", "Edit", "$session_name added item $name to recurring invoice $recurring_invoice_prefix$recurring_invoice_number", $client_id, $recurring_invoice_id);
flash_alert("Item <srrong>$name</strong> added to Recurring Invoice");
redirect();
}
if (isset($_POST['recurring_invoice_note'])) {
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
$note = sanitizeInput($_POST['note']);
// Get Recurring details for logging
$sql = mysqli_query($mysqli,"SELECT recurring_invoice_prefix, recurring_invoice_number, recurring_invoice_client_id FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$client_id = intval($row['recurring_invoice_client_id']);
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_note = '$note' WHERE recurring_invoice_id = $recurring_invoice_id");
logAction("Recurring Invoice", "Edit", "$session_name added note to recurring invoice $recurring_invoice_prefix$recurring_invoice_number", $client_id, $recurring_invoice_id);
flash_alert("Notes added");
redirect();
}
if (isset($_GET['delete_recurring_invoice_item'])) {
$item_id = intval($_GET['delete_recurring_invoice_item']);
$sql = mysqli_query($mysqli,"SELECT * FROM invoice_items WHERE item_id = $item_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_id = intval($row['item_recurring_invoice_id']);
$item_name = sanitizeInput($row['item_name']);
$item_subtotal = floatval($row['item_subtotal']);
$item_tax = floatval($row['item_tax']);
$item_total = floatval($row['item_total']);
$sql = mysqli_query($mysqli,"SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$client_id = intval($row['recurring_invoice_client_id']);
$new_recurring_invoice_amount = floatval($row['recurring_invoice_amount']) - $item_total;
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_amount = $new_recurring_invoice_amount WHERE recurring_invoice_id = $recurring_invoice_id");
mysqli_query($mysqli,"DELETE FROM invoice_items WHERE item_id = $item_id");
logAction("Recurring Invoice", "Edit", "$session_name removed item $item_name from recurring invoice $recurring_invoice_prefix$recurring_invoice_number", $client_id);
flash_alert("Item <strong>$item_name</strong> removed", 'error');
redirect();
}
if (isset($_GET['force_recurring'])) {
$recurring_invoice_id = intval($_GET['force_recurring']);
$sql_recurring_invoices = mysqli_query($mysqli,"SELECT * FROM recurring_invoices, clients WHERE client_id = recurring_invoice_client_id AND recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql_recurring_invoices);
$recurring_invoice_id = intval($row['recurring_invoice_id']);
$recurring_invoice_scope = sanitizeInput($row['recurring_invoice_scope']);
$recurring_invoice_frequency = sanitizeInput($row['recurring_invoice_frequency']);
$recurring_invoice_status = sanitizeInput($row['recurring_invoice_status']);
$recurring_invoice_last_sent = sanitizeInput($row['recurring_invoice_last_sent']);
$recurring_invoice_next_date = sanitizeInput($row['recurring_invoice_next_date']);
$recurring_invoice_discount_amount = floatval($row['recurring_invoice_discount_amount']);
$recurring_invoice_amount = floatval($row['recurring_invoice_amount']);
$recurring_invoice_currency_code = sanitizeInput($row['recurring_invoice_currency_code']);
$recurring_invoice_note = sanitizeInput($row['recurring_invoice_note']);
$category_id = intval($row['recurring_invoice_category_id']);
$client_id = intval($row['recurring_invoice_client_id']);
$client_net_terms = intval($row['client_net_terms']);
//Get the last Invoice Number and add 1 for the new invoice number
$new_invoice_number = $config_invoice_next_number;
$new_config_invoice_next_number = $config_invoice_next_number + 1;
mysqli_query($mysqli,"UPDATE settings SET config_invoice_next_number = $new_config_invoice_next_number WHERE company_id = 1");
//Generate a unique URL key for clients to access
$url_key = randomString(156);
mysqli_query($mysqli,"INSERT INTO invoices SET invoice_prefix = '$config_invoice_prefix', invoice_number = $new_invoice_number, invoice_scope = '$recurring_invoice_scope', invoice_date = CURDATE(), invoice_due = DATE_ADD(CURDATE(), INTERVAL $client_net_terms day), invoice_discount_amount = $recurring_invoice_discount_amount, invoice_amount = $recurring_invoice_amount, invoice_currency_code = '$recurring_invoice_currency_code', invoice_note = '$recurring_invoice_note', invoice_category_id = $category_id, invoice_status = 'Sent', invoice_url_key = '$url_key', invoice_recurring_invoice_id = $recurring_invoice_id, invoice_client_id = $client_id");
$new_invoice_id = mysqli_insert_id($mysqli);
//Copy Items from original invoice to new invoice
$sql_invoice_items = mysqli_query($mysqli,"SELECT * FROM invoice_items WHERE item_recurring_invoice_id = $recurring_invoice_id ORDER BY item_id ASC");
while($row = mysqli_fetch_array($sql_invoice_items)) {
$item_id = intval($row['item_id']);
$item_name = sanitizeInput($row['item_name']);
$item_description = sanitizeInput($row['item_description']);
$item_quantity = floatval($row['item_quantity']);
$item_price = floatval($row['item_price']);
$item_subtotal = floatval($row['item_subtotal']);
$item_order = intval($row['item_order']);
$tax_id = intval($row['item_tax_id']);
//Recalculate Item Tax since Tax percents can change.
if ($tax_id > 0) {
$sql = mysqli_query($mysqli,"SELECT * FROM taxes WHERE tax_id = $tax_id");
$row = mysqli_fetch_array($sql);
$tax_percent = floatval($row['tax_percent']);
$item_tax_amount = $item_subtotal * $tax_percent / 100;
} else {
$item_tax_amount = 0;
}
$item_total = $item_subtotal + $item_tax_amount;
//Update Recurring Items with new tax
mysqli_query($mysqli,"UPDATE invoice_items SET item_tax = $item_tax_amount, item_total = $item_total, item_tax_id = $tax_id, item_order = $item_order WHERE item_id = $item_id");
mysqli_query($mysqli,"INSERT INTO invoice_items SET item_name = '$item_name', item_description = '$item_description', item_quantity = $item_quantity, item_price = $item_price, item_subtotal = $item_subtotal, item_tax = $item_tax_amount, item_total = $item_total, item_tax_id = $tax_id, item_invoice_id = $new_invoice_id");
}
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Invoice Generated from Recurring!', history_invoice_id = $new_invoice_id");
//Update Recurring Balances by tallying up recurring items also update recurring dates
$sql_recurring_invoice_total = mysqli_query($mysqli,"SELECT SUM(item_total) AS recurring_invoice_total FROM invoice_items WHERE item_recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql_recurring_invoice_total);
$new_recurring_invoice_amount = floatval($row['recurring_invoice_total']) - $recurring_invoice_discount_amount;
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_amount = $new_recurring_invoice_amount, recurring_invoice_last_sent = CURDATE(), recurring_invoice_next_date = DATE_ADD(CURDATE(), INTERVAL 1 $recurring_invoice_frequency) WHERE recurring_invoice_id = $recurring_invoice_id");
//Also update the newly created invoice with the new amounts
mysqli_query($mysqli,"UPDATE invoices SET invoice_amount = $new_recurring_invoice_amount WHERE invoice_id = $new_invoice_id");
if ($config_recurring_auto_send_invoice == 1) {
$sql = mysqli_query($mysqli,"SELECT * FROM invoices
LEFT JOIN clients ON invoice_client_id = client_id
LEFT JOIN contacts ON clients.client_id = contacts.contact_client_id AND contact_primary = 1
WHERE invoice_id = $new_invoice_id"
);
$row = mysqli_fetch_array($sql);
$invoice_prefix = sanitizeInput($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_scope = sanitizeInput($row['invoice_scope']);
$invoice_date = sanitizeInput($row['invoice_date']);
$invoice_due = sanitizeInput($row['invoice_due']);
$invoice_amount = floatval($row['invoice_amount']);
$invoice_url_key = sanitizeInput($row['invoice_url_key']);
$client_id = intval($row['client_id']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$contact_phone = sanitizeInput(formatPhoneNumber($row['contact_phone'], $row['contact_phone_country_code']));
$contact_extension = intval($row['contact_extension']);
$contact_mobile = sanitizeInput(formatPhoneNumber($row['contact_mobile'], $row['contact_mobile_country_code']));
$sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
$company_email = sanitizeInput($row['company_email']);
$company_website = sanitizeInput($row['company_website']);
// Sanitize Config Vars
$config_invoice_from_email = sanitizeInput($config_invoice_from_email);
$config_invoice_from_name = sanitizeInput($config_invoice_from_name);
// Email to client
$subject = "Invoice $invoice_prefix$invoice_number";
$body = "Hello $contact_name,<br><br>An invoice regarding \"$invoice_scope\" has been generated. Please view the details below.<br><br>Invoice: $invoice_prefix$invoice_number<br>Issue Date: $invoice_date<br>Total: $$invoice_amount<br>Due Date: $invoice_due<br><br><br>To view your invoice, please click <a href=\'https://$config_base_url/guest/guest_view_invoice.php?invoice_id=$new_invoice_id&url_key=$invoice_url_key\'>here</a>.<br><br><br>--<br>$company_name - Billing<br>$company_phone";
$data = [
[
'from' => $config_invoice_from_email,
'from_name' => $config_invoice_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body
]
];
$mail = addToMailQueue($data);
if ($mail === true) {
// Add send history
mysqli_query($mysqli,"INSERT INTO history SET history_status = 'Sent', history_description = 'Force Emailed Invoice!', history_invoice_id = $new_invoice_id");
// Update Invoice Status to Sent
mysqli_query($mysqli,"UPDATE invoices SET invoice_status = 'Sent', invoice_client_id = $client_id WHERE invoice_id = $new_invoice_id");
} else {
// Error reporting
appNotify("Mail", "Failed to send email to $contact_email");
logAction("Mail", "Error", "Failed to send email to $contact_email regarding $subject. $mail");
}
} //End Recurring Invoices Loop
logAction("Invoice", "Create", "$session_name forced recurring invoice into an invoice", $client_id, $new_invoice_id);
customAction('invoice_create', $new_invoice_id);
flash_alert("Recurring Invoice Forced");
redirect();
}
if (isset($_POST['set_recurring_payment'])) {
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
$saved_payment_id = intval($_POST['saved_payment_id']);
// Get Recurring Invoice Info for logging and alerting
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['recurring_invoice_client_id']);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$recurring_invoice_currency_code = sanitizeInput($row['recurring_invoice_currency_code']);
$recurring_invoice_amount = floatval($row['recurring_invoice_amount']);
if ($saved_payment_id) {
// Get Payment provider and method
$sql = mysqli_query($mysqli, "
SELECT * FROM payment_providers
LEFT JOIN client_saved_payment_methods ON saved_payment_provider_id = payment_provider_id
WHERE saved_payment_id = $saved_payment_id
");
$row = mysqli_fetch_array($sql);
$provider_id = intval($row['payment_provider_id']);
$provider_name = sanitizeInput($row['payment_provider_name']);
$account_id = intval($row['payment_provider_account']);
$saved_payment_description = sanitizeInput($row['saved_payment_description']);
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id");
mysqli_query($mysqli,"INSERT INTO recurring_payments SET recurring_payment_currency_code = '$recurring_invoice_currency_code', recurring_payment_account_id = $account_id, recurring_payment_method = 'Credit Card', recurring_payment_recurring_invoice_id = $recurring_invoice_id, recurring_payment_saved_payment_id = $saved_payment_id");
// Get Payment ID for reference
$recurring_payment_id = mysqli_insert_id($mysqli);
logAction("Recurring Invoice", "Auto Payment", "$session_name created Auto Pay for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number in the amount of " . numfmt_format_currency($currency_format, $recurring_invoice_amount, $recurring_invoice_currency_code), $client_id, $recurring_invoice_id);
flash_alert("Automatic Payment <strong>$saved_payment_description</strong> enabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number");
} else {
// Delete
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id");
logAction("Recurring Invoice", "Auto Payment", "$session_name removed Auto Pay for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number in the amount of " . numfmt_format_currency($currency_format, $recurring_invoice_amount, $recurring_invoice_currency_code), $client_id, $recurring_invoice_id);
flash_alert("Automatic Payment <strong>Disabled</strong> for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number", 'error');
}
redirect();
}
if (isset($_POST['export_client_recurring_invoice_csv'])) {
$client_id = intval($_POST['client_id']);
//get records from database
$sql = mysqli_query($mysqli,"SELECT client_name FROM clients WHERE client_id = $client_id");
$row = mysqli_fetch_array($sql);
$client_name = $row['client_name'];
$sql = mysqli_query($mysqli,"SELECT * FROM recurring_invoices WHERE recurring_invoice_client_id = $client_id ORDER BY recurring_invoice_number ASC");
$num_rows = mysqli_num_rows($sql);
if ($num_rows > 0) {
$delimiter = ",";
$filename = $client_name . "-Recurring Invoices-" . date('Y-m-d') . ".csv";
//create a file pointer
$f = fopen('php://memory', 'w');
//set column headers
$fields = array('Recurring Number', 'Scope', 'Amount', 'Frequency', 'Date Created');
fputcsv($f, $fields, $delimiter);
//output each row of the data, format line as csv and write to file pointer
while($row = $sql->fetch_assoc()) {
$lineData = array($row['recurring_invoice_prefix'] . $row['recurring_invoice_number'], $row['recurring_invoice_scope'], $row['recurring_invoice_amount'], ucwords($row['recurring_invoice_frequency'] . "ly"), $row['recurring_invoice_created_at']);
fputcsv($f, $lineData, $delimiter);
}
//move back to beginning of file
fseek($f, 0);
//set headers to download file rather than displayed
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="' . $filename . '";');
//output all remaining data on a file pointer
fpassthru($f);
}
logAction("Recurring Invoice", "Export", "$session_name exported $num_rows recurring invoices to CSV file");
exit;
}
if (isset($_GET['recurring_invoice_email_notify'])) {
$recurring_invoice_email_notify = intval($_GET['recurring_invoice_email_notify']);
$recurring_invoice_id = intval($_GET['recurring_invoice_id']);
$sql = mysqli_query($mysqli,"SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
$row = mysqli_fetch_array($sql);
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$client_id = intval($row['recurring_invoice_client_id']);
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_email_notify = $recurring_invoice_email_notify WHERE recurring_invoice_id = $recurring_invoice_id");
// Wording
if ($recurring_invoice_email_notify) {
$notify_wording = "On";
} else {
$notify_wording = "Off";
}
logAction("Recurring Invoice", "Edit", "$session_name turned $notify_wording Email Notifications for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number", $client_id, $recurring_invoice_id);
flash_alert("Email Notifications <strong>$notify_wording</strong>", 'error');
redirect();
}

View File

@@ -0,0 +1,636 @@
<?php
/*
* ITFlow - GET/POST request handler for recurring tickets
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_recurring_ticket'])) {
enforceUserPermission('module_support', 2);
require_once 'ticket_recurring_model.php';
$start_date = sanitizeInput($_POST['start_date']);
mysqli_query($mysqli, "INSERT INTO recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_start_date = '$start_date', recurring_ticket_next_run = '$start_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_created_by = $session_user_id, recurring_ticket_client_id = $client_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_asset_id = $asset_id, recurring_ticket_category = $category");
$recurring_ticket_id = mysqli_insert_id($mysqli);
// Add Additional Assets
if (isset($_POST['additional_assets'])) {
foreach ($_POST['additional_assets'] as $additional_asset) {
$additional_asset_id = intval($additional_asset);
mysqli_query($mysqli, "INSERT INTO recurring_ticket_assets SET recurring_ticket_id = $recurring_ticket_id, asset_id = $additional_asset_id");
}
}
logAction("Recurring Ticket", "Create", "$session_name created recurring ticket for $subject - $frequency", $client_id, $recurring_ticket_id);
flash_alert("Recurring ticket <strong>$subject - $frequency</strong> created");
redirect();
}
if (isset($_POST['edit_recurring_ticket'])) {
enforceUserPermission('module_support', 2);
require_once 'ticket_recurring_model.php';
$recurring_ticket_id = intval($_POST['recurring_ticket_id']);
$next_run_date = sanitizeInput($_POST['next_date']);
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_next_run = '$next_run_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_asset_id = $asset_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_category = $category WHERE recurring_ticket_id = $recurring_ticket_id");
// Add Additional Assets
if (isset($_POST['additional_assets'])) {
mysqli_query($mysqli, "DELETE FROM recurring_ticket_assets WHERE recurring_ticket_id = $recurring_ticket_id");
foreach ($_POST['additional_assets'] as $additional_asset) {
$additional_asset_id = intval($additional_asset);
mysqli_query($mysqli, "INSERT INTO recurring_ticket_assets SET recurring_ticket_id = $recurring_ticket_id, asset_id = $additional_asset_id");
}
}
logAction("Recurring Ticket", "Edit", "$session_name edited recurring ticket $subject", $client_id, $recurring_ticket_id);
flash_alert("Recurring ticket <strong>$subject - $frequency</strong> updated");
redirect();
}
if (isset($_POST['bulk_force_recurring_tickets'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_support', 2);
if (isset($_POST['recurring_ticket_ids'])) {
// Cycle through array and pop each recurring scheduled ticket
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
if (mysqli_num_rows($sql) > 0) {
$row = mysqli_fetch_array($sql);
$subject = sanitizeInput($row['recurring_ticket_subject']);
$details = mysqli_real_escape_string($mysqli, $row['recurring_ticket_details']);
$priority = sanitizeInput($row['recurring_ticket_priority']);
$frequency = sanitizeInput(strtolower($row['recurring_ticket_frequency']));
$billable = intval($row['recurring_ticket_billable']);
$old_next_recurring_date = sanitizeInput($row['recurring_ticket_next_run']);
$created_id = intval($row['recurring_ticket_created_by']);
$assigned_id = intval($row['recurring_ticket_assigned_to']);
$contact_id = intval($row['recurring_ticket_contact_id']);
$client_id = intval($row['recurring_ticket_client_id']);
$asset_id = intval($row['recurring_ticket_asset_id']);
$category = intval($row['recurring_ticket_category']);
$url_key = randomString(156);
$ticket_status = 1; // Default
if ($assigned_id > 0) {
$ticket_status = 2; // Set to open if we've auto-assigned an agent
}
// Sanitize Config Vars from get_settings.php and Session Vars from check_login.php
$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_base_url = sanitizeInput($config_base_url);
// Assign this new ticket the next ticket number & increment config_ticket_next_number by 1 (for the next ticket)
$ticket_number_sql = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_ticket_next_number FROM settings WHERE company_id = 1"));
$ticket_number = intval($ticket_number_sql['config_ticket_next_number']);
$new_config_ticket_next_number = $ticket_number + 1;
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
// Raise the ticket
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Recurring', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = '$ticket_status', ticket_billable = $billable, ticket_url_key = '$url_key', ticket_created_by = $created_id, ticket_assigned_to = $assigned_id, ticket_contact_id = $contact_id, ticket_client_id = $client_id, ticket_asset_id = $asset_id, ticket_category = $category, ticket_recurring_ticket_id = $recurring_ticket_id");
$id = mysqli_insert_id($mysqli);
// Copy Additional Assets from Recurring ticket to new ticket
mysqli_query($mysqli, "INSERT INTO ticket_assets (ticket_id, asset_id)
SELECT $id, asset_id
FROM recurring_ticket_assets
WHERE recurring_ticket_id = $recurring_ticket_id");
// Notifications
customAction('ticket_create', $id);
// Get client/contact/ticket details
$sql = mysqli_query(
$mysqli,
"SELECT client_name, contact_name, contact_email, ticket_prefix, ticket_number, ticket_priority, ticket_subject, ticket_details FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
WHERE ticket_id = $id"
);
$row = mysqli_fetch_array($sql);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_priority = sanitizeInput($row['ticket_priority']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_details = mysqli_real_escape_string($mysqli, $row['ticket_details']);
$data = [];
// Notify client by email their ticket has been raised, if general notifications are turned on & there is a valid contact email
if (!empty($config_smtp_host) && $config_ticket_client_general_notifications == 1 && filter_var($contact_email, FILTER_VALIDATE_EMAIL)) {
$email_subject = "Ticket Created - [$ticket_prefix$ticket_number] - $ticket_subject (scheduled)";
$email_body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>A ticket regarding \"$ticket_subject\" has been automatically created for you.<br><br>--------------------------------<br>$ticket_details--------------------------------<br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: Open<br>Portal: https://$config_base_url/client/ticket.php?id=$id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$email = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $email_subject,
'body' => $email_body
];
$data[] = $email;
}
// Add to the mail queue
addToMailQueue($data);
// Set the next run date (based on the scheduled date, rather than now, so things keep their schedule)
$dt_old_next_recurring_date = new DateTime($old_next_recurring_date);
if ($frequency == "weekly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 week'));
} elseif ($frequency == "monthly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 month'));
} elseif ($frequency == "quarterly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('3 months'));
} elseif ($frequency == "biannually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('6 months'));
} elseif ($frequency == "annually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('12 months'));
}
// Update the run date
$next_run = $next_run->format('Y-m-d');
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_next_run = '$next_run' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Ticket", "Create", "$session_name force created recurring scheduled $frequency ticket - $config_ticket_prefix$ticket_number - $subject", $client_id, $id);
}
}
flash_alert("$count Recurring Tickets Forced");
}
redirect();
}
if (isset($_GET['force_recurring_ticket'])) {
validateCSRFToken($_GET['csrf_token']);
enforceUserPermission('module_support', 2);
$recurring_ticket_id = intval($_GET['force_recurring_ticket']);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
if (mysqli_num_rows($sql) > 0) {
$row = mysqli_fetch_array($sql);
$subject = sanitizeInput($row['recurring_ticket_subject']);
$details = mysqli_real_escape_string($mysqli, $row['recurring_ticket_details']);
$priority = sanitizeInput($row['recurring_ticket_priority']);
$frequency = sanitizeInput(strtolower($row['recurring_ticket_frequency']));
$billable = intval($row['recurring_ticket_billable']);
$old_next_recurring_date = sanitizeInput($row['recurring_ticket_next_run']);
$created_id = intval($row['recurring_ticket_created_by']);
$assigned_id = intval($row['recurring_ticket_assigned_to']);
$contact_id = intval($row['recurring_ticket_contact_id']);
$client_id = intval($row['recurring_ticket_client_id']);
$asset_id = intval($row['recurring_ticket_asset_id']);
$category = intval($row['recurring_ticket_category']);
$url_key = randomString(156);
$ticket_status = 1; // Default
if ($assigned_id > 0) {
$ticket_status = 2; // Set to open if we've auto-assigned an agent
}
// Sanitize Config Vars from get_settings.php and Session Vars from check_login.php
$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_base_url = sanitizeInput($config_base_url);
// Assign this new ticket the next ticket number & increment config_ticket_next_number by 1 (for the next ticket)
$ticket_number = $config_ticket_next_number;
$new_config_ticket_next_number = $config_ticket_next_number + 1;
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
// Raise the ticket
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Recurring', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = '$ticket_status', ticket_billable = $billable, ticket_url_key = '$url_key', ticket_created_by = $created_id, ticket_assigned_to = $assigned_id, ticket_contact_id = $contact_id, ticket_client_id = $client_id, ticket_asset_id = $asset_id, ticket_category = $category, ticket_recurring_ticket_id = $recurring_ticket_id");
$id = mysqli_insert_id($mysqli);
// Copy Additional Assets from Recurring ticket to new ticket
mysqli_query($mysqli, "INSERT INTO ticket_assets (ticket_id, asset_id)
SELECT $id, asset_id
FROM recurring_ticket_assets
WHERE recurring_ticket_id = $recurring_ticket_id");
// Notifications
customAction('ticket_create', $id);
// Get client/contact/ticket details
$sql = mysqli_query(
$mysqli,
"SELECT client_name, contact_name, contact_email, ticket_prefix, ticket_number, ticket_priority, ticket_subject, ticket_details FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
WHERE ticket_id = $id"
);
$row = mysqli_fetch_array($sql);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_priority = sanitizeInput($row['ticket_priority']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_details = mysqli_real_escape_string($mysqli, $row['ticket_details']);
$data = [];
// Notify client by email their ticket has been raised, if general notifications are turned on & there is a valid contact email
if (!empty($config_smtp_host) && $config_ticket_client_general_notifications == 1 && filter_var($contact_email, FILTER_VALIDATE_EMAIL)) {
$email_subject = "Ticket created - [$ticket_prefix$ticket_number] - $ticket_subject (scheduled)";
$email_body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>A ticket regarding \"$ticket_subject\" has been automatically created for you.<br><br>--------------------------------<br>$ticket_details--------------------------------<br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: Open<br>Portal: https://$config_base_url/client/ticket.php?id=$id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$email = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $email_subject,
'body' => $email_body
];
$data[] = $email;
}
// Add to the mail queue
addToMailQueue($data);
// Set the next run date (based on the scheduled date, rather than now, so things keep their schedule)
$dt_old_next_recurring_date = new DateTime($old_next_recurring_date);
if ($frequency == "weekly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 week'));
} elseif ($frequency == "monthly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 month'));
} elseif ($frequency == "quarterly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('3 months'));
} elseif ($frequency == "biannually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('6 months'));
} elseif ($frequency == "annually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('12 months'));
}
// Update the run date
$next_run = $next_run->format('Y-m-d');
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_next_run = '$next_run' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Ticket", "Create", "$session_name force created recurring scheduled $frequency ticket - $config_ticket_prefix$ticket_number - $subject", $client_id, $id);
flash_alert("Recurring Ticket Forced");
redirect();
} else {
flash_alert("Recurring Ticket Force failed", 'error');
redirect();
}
}
if (isset($_GET['delete_recurring_ticket'])) {
validateCSRFToken($_GET['csrf_token']);
enforceUserPermission('module_support', 3);
$recurring_ticket_id = intval($_GET['delete_recurring_ticket']);
// Get Scheduled Ticket Subject Ticket Prefix, Number and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$subject = sanitizeInput($row['recurring_ticket_subject']);
$frequency = sanitizeInput($row['recurring_ticket_frequency']);
$client_id = intval($row['recurring_ticket_client_id']);
// Delete
mysqli_query($mysqli, "DELETE FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Delete", "$session_name deleted recurring ticket $subject", $client_id, $recurring_ticket_id);
flash_alert("Recurring ticket <strong>$subject - $frequency</strong> deleted", 'error');
redirect();
}
if (isset($_POST['bulk_delete_recurring_tickets'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_support', 3);
if (isset($_POST['recurring_ticket_ids'])) {
$count = count($_POST['recurring_ticket_ids']);
// Cycle through array and delete each recurring scheduled ticket
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
mysqli_query($mysqli, "DELETE FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Delete", "$session_name deleted recurring ticket", 0, $recurring_ticket_id);
}
logAction("Recurring Ticket", "Bulk Delete", "$session_name deleted $count recurring ticket(s)");
flash_alert("Deleted <strong>$count</strong> recurring ticket(s)", 'error');
}
redirect();
}
if (isset($_POST['bulk_assign_recurring_ticket'])) {
enforceUserPermission('module_support', 2);
// POST variables
$assign_to = intval($_POST['assign_to']);
// Get a Recurring Ticket Count
$recurring_ticket_count = count($_POST['recurring_ticket_ids']);
// Assign Tech to Selected Recurring Tickets
if (!empty($_POST['recurring_ticket_ids'])) {
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$recurring_ticket_name = sanitizeInput($row['recurring_ticket_name']);
$recurring_ticket_subject = sanitizeInput($row['recurring_ticket_subject']);
$client_id = intval($row['recurring_ticket_client_id']);
// Allow for un-assigning tickets
if ($assign_to == 0) {
$ticket_reply = "Ticket unassigned, pending re-assignment.";
$agent_name = "No One";
} else {
// Get & verify assigned agent details
$agent_details_sql = mysqli_query($mysqli, "SELECT user_name, user_email FROM users LEFT JOIN user_settings ON users.user_id = user_settings.user_id WHERE users.user_id = $assign_to");
$agent_details = mysqli_fetch_array($agent_details_sql);
$agent_name = sanitizeInput($agent_details['user_name']);
$agent_email = sanitizeInput($agent_details['user_email']);
if (!$agent_name) {
flash_alert("Invalid agent!", 'error');
redirect();
}
}
// Update recurring ticket
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_assigned_to = $assign_to WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring_Ticket", "Edit", "$session_name reassigned recurring ticket $recurring_ticket_subject to $agent_name", $client_id, $recurring_ticket_id);
$tickets_assigned_body .= "$recurring_ticket_subject<br>";
} // End For Each Ticket ID Loop
// Notification
if ($session_user_id != $assign_to && $assign_to != 0) {
// App Notification
mysqli_query($mysqli, "INSERT INTO notifications SET notification_type = 'Recurring Ticket', notification = '$recurring_ticket_count Recurring Tickets have been assigned to you by $session_name', notification_action = 'recurring_tickets.php?assigned=$assign_to', notification_client_id = $client_id, notification_user_id = $assign_to");
// Agent Email Notification
if (!empty($config_smtp_host)) {
// Sanitize Config vars from get_settings.php
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$company_name = sanitizeInput($session_company_name);
$subject = "$config_app_name - $recurring_ticket_count recurring tickets have been assigned to you";
$body = "Hi $agent_name, <br><br>$session_name assigned $recurring_ticket_count recurring tickets to you!<br><br>$tickets_assigned_body<br>Thanks, <br>$session_name<br>$company_name";
// Email Ticket Agent
// Queue Mail
$data = [
[
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $agent_email,
'recipient_name' => $agent_name,
'subject' => $subject,
'body' => $body,
]
];
addToMailQueue($data);
}
}
}
flash_alert("Assigned <strong>$recurring_ticket_count</strong> Recurring Tickets to <strong>$agent_name</strong>");
redirect();
}
if (isset($_POST['bulk_edit_recurring_ticket_priority'])) {
enforceUserPermission('module_support', 2);
$priority = sanitizeInput($_POST['bulk_priority']);
// Assign Tech to Selected Recurring Tickets
if (isset($_POST['recurring_ticket_ids'])) {
// Get a Ticket Count
$recurring_ticket_count = count($_POST['recurring_ticket_ids']);
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$recurring_ticket_subject = sanitizeInput($row['recurring_ticket_subject']);
$original_recurring_ticket_priority = sanitizeInput($row['recurring_ticket_priority']);
$client_id = intval($row['ticket_client_id']);
// Update recurring ticket
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_priority = '$priority' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Ticket", "Edit", "$session_name updated the priority on recurring ticket $ticket_subject from $original_recurring_ticket_priority to $priority", $client_id, $recurring_ticket_id);
customAction('recurring_ticket_update', $recurring_ticket_id);
} // End For Each Recurring Ticket ID Loop
logAction("Recurring Ticket", " Bulk Edit", "$session_name updated the priority to $priority on $recurring_ticket_count Recurring Tickets");
flash_alert("Priority updated to <strong>$priority</strong> for <strong>$recurring_ticket_count</strong> Recurring Tickets");
}
redirect();
}
if (isset($_POST['bulk_edit_recurring_ticket_category'])) {
enforceUserPermission('module_support', 2);
$category_id = intval($_POST['bulk_category']);
if (isset($_POST['recurring_ticket_ids'])) {
$recurring_ticket_count = count($_POST['recurring_ticket_ids']);
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT recurring_ticket_subject, category_name, recurring_ticket_client_id FROM recurring_tickets LEFT JOIN categories ON recurring_ticket_category = category_id WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$recurring_ticket_subject = sanitizeInput($row['recurring_ticket_subject']);
$previous_recurring_ticket_category_name = sanitizeInput($row['category_name']);
$client_id = intval($row['recurring_ticket_client_id']);
$category_name = sanitizeInput(getFieldById('categories', $category_id, 'category_name'));
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_category = '$category_id' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Edit", "$session_name updated the category on recurring ticket $recurring_ticket_subject from $previous_recurring_ticket_category_name to $category_name", $client_id, $recurring_ticket_id);
customAction('recurring_ticket_update', $recurring_ticket_id);
}
logAction("Recurring Ticket", " Bulk Edit", "$session_name updated the category to $category_name for $recurring_ticket_count Recurring Tickets");
flash_alert("Category set to $category_name for <strong>$recurring_ticket_count</strong> Recurring Tickets");
}
redirect();
}
if (isset($_POST['bulk_edit_recurring_ticket_billable'])) {
enforceUserPermission('module_support', 2);
enforceUserPermission('module_sales', 2);
$billable = intval($_POST['billable']);
if ($billable) {
$billable_status = "Billable";
} else {
$billable_status = "Not Billable";
}
if (isset($_POST['recurring_ticket_ids'])) {
$recurring_ticket_count = count($_POST['recurring_ticket_ids']);
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT recurring_ticket_subject, recurring_ticket_client_id FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$recurring_ticket_subject = sanitizeInput($row['recurring_ticket_subject']);
$previous_recurring_ticket_billable = intval($row['recurring_ticket_billable']);
if ($previous_recurring_ticket_billable) {
$previous_billable_status = "Billable";
} else {
$previous_billable_status = "Not Billable";
}
$client_id = intval($row['recurring_ticket_client_id']);
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_billable = $billable WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Edit", "$session_name updated the billable status on recurring ticket $recurring_ticket_subject from $previous_billable_status to $billable_status", $client_id, $recurring_ticket_id);
customAction('recurring_ticket_update', $recurring_ticket_id);
}
logAction("Recurring Ticket", " Bulk Edit", "$session_name updated the billable status to $billable_status for $recurring_ticket_count Recurring Tickets");
flash_alert("Billable status set to $billable_status for <strong>$recurring_ticket_count</strong> Recurring Tickets");
}
redirect();
}
if (isset($_POST['bulk_edit_recurring_ticket_next_run_date'])) {
enforceUserPermission('module_support', 2);
$next_run_date = sanitizeInput($_POST['next_run_date']);
if (isset($_POST['recurring_ticket_ids'])) {
$recurring_ticket_count = count($_POST['recurring_ticket_ids']);
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT recurring_ticket_subject, recurring_ticket_client_id FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$recurring_ticket_subject = sanitizeInput($row['recurring_ticket_subject']);
$previous_recurring_ticket_next_run_date = sanitizeInput($row['recurring_ticket_next_run']);
$client_id = intval($row['recurring_ticket_client_id']);
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_next_run = '$next_run_date' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Edit", "$session_name updated the Next run date on recurring ticket $recurring_ticket_subject from $previous_recurring_ticket_next_run_date to $next_run_date", $client_id, $recurring_ticket_id);
customAction('recurring_ticket_update', $recurring_ticket_id);
}
logAction("Recurring Ticket", " Bulk Edit", "$session_name updated the Next run date to $next_run_date for $recurring_ticket_count Recurring Tickets");
flash_alert("Next run date set to <strong>$next_run_date</strong> for <strong>$recurring_ticket_count</strong> Recurring Tickets");
}
redirect();
}

View File

@@ -131,10 +131,9 @@ if (isset($_POST['add_ticket'])) {
$company_name = sanitizeInput($row['company_name']); $company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code'])); $company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// EMAILING // EMAILING
$subject = "Ticket created [$ticket_prefix$ticket_number] - $ticket_subject"; $subject = "Ticket Created [$ticket_prefix$ticket_number] - $ticket_subject";
$body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>A ticket regarding \"$ticket_subject\" has been created for you.<br><br>--------------------------------<br>$ticket_details--------------------------------<br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: Open<br>Portal: <a href=\'https://$config_base_url/guest/guest_view_ticket.php?ticket_id=$ticket_id&url_key=$url_key\'>View ticket</a><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone"; $body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>A ticket regarding \"$ticket_subject\" has been created for you.<br><br>--------------------------------<br>$ticket_details--------------------------------<br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: Open<br>Portal: <a href=\'https://$config_base_url/guest/guest_view_ticket.php?ticket_id=$ticket_id&url_key=$url_key\'>View ticket</a><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
// Verify contact email is valid // Verify contact email is valid
@@ -234,7 +233,7 @@ if (isset($_POST['edit_ticket'])) {
} }
// Get contact/ticket details after update for logging / email purposes // Get contact/ticket details after update for logging / email purposes
$sql = mysqli_query($mysqli, "SELECT contact_name, contact_email, ticket_prefix, ticket_number, ticket_category, ticket_details, ticket_status_name, ticket_created_by, ticket_assigned_to, ticket_client_id FROM tickets $sql = mysqli_query($mysqli, "SELECT contact_name, contact_email, ticket_prefix, ticket_number, ticket_category, ticket_details, ticket_status_name, ticket_created_by, ticket_assigned_to, ticket_url_key, ticket_client_id FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id LEFT JOIN contacts ON ticket_contact_id = contact_id
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
@@ -251,6 +250,7 @@ if (isset($_POST['edit_ticket'])) {
$ticket_status = sanitizeInput($row['ticket_status_name']); $ticket_status = sanitizeInput($row['ticket_status_name']);
$ticket_created_by = intval($row['ticket_created_by']); $ticket_created_by = intval($row['ticket_created_by']);
$ticket_assigned_to = intval($row['ticket_assigned_to']); $ticket_assigned_to = intval($row['ticket_assigned_to']);
$url_key = sanitizeInput($row['ticket_url_key']);
$client_id = intval($row['ticket_client_id']); $client_id = intval($row['ticket_client_id']);
// Notify new contact if selected // Notify new contact if selected
@@ -416,6 +416,28 @@ if (isset($_POST['edit_ticket_contact'])) {
} }
if (isset($_POST['edit_ticket_project'])) {
enforceUserPermission('module_support', 2);
$ticket_id = intval($_POST['ticket_id']);
$project_id = intval($_POST['project']);
$project_name = sanitizeInput(getFieldById('projects', $project_id, 'project_name'));
$client_id = intval(getFieldById('tickets', $ticket_id, 'ticket_client_id'));
$ticket_prefix = sanitizeInput(getFieldById('tickets', $ticket_id, 'ticket_prefix'));
$ticket_number = sanitizeInput(getFieldById('tickets', $ticket_id, 'ticket_number'));
mysqli_query($mysqli, "UPDATE tickets SET ticket_project_id = $project_id WHERE ticket_id = $ticket_id");
logAction("Ticket", "Edit", "$session_name set ticket $ticket_prefix$ticket_number project to $project_name", $client_id, $ticket_id);
flash_alert("Project changed to <strong>$project_name</strong> for Ticket <strong>$ticket_prefix$ticket_number</strong>");
redirect();
}
if (isset($_POST['add_ticket_watcher'])) { if (isset($_POST['add_ticket_watcher'])) {
enforceUserPermission('module_support', 2); enforceUserPermission('module_support', 2);
@@ -1539,13 +1561,12 @@ if (isset($_POST['bulk_add_asset_ticket'])) {
} }
if (isset($_POST['add_ticket_reply'])) { if (isset($_POST['add_ticket_reply'])) {
enforceUserPermission('module_support', 2); enforceUserPermission('module_support', 2);
$ticket_id = intval($_POST['ticket_id']); $ticket_id = intval($_POST['ticket_id']);
$ticket_reply = mysqli_real_escape_string($mysqli, $_POST['ticket_reply']); $ticket_reply = $_POST['ticket_reply']; // Reply is SQL escaped below
$ticket_status = intval($_POST['status']); $ticket_status = intval($_POST['status']);
$client_id = intval($_POST['client_id']); $client_id = intval($_POST['client_id']);
@@ -1566,6 +1587,12 @@ if (isset($_POST['add_ticket_reply'])) {
} else { } else {
$ticket_reply_type = 'Internal'; $ticket_reply_type = 'Internal';
} }
// Add Signature to the end of the ticket reply if not Internal and if there is reply
if ($ticket_reply !== '' && $ticket_reply_type !== 'Internal') {
$ticket_reply .= getFieldById('user_settings',$session_user_id,'user_config_signature', 'raw');
}
$ticket_reply = mysqli_escape_string($mysqli, $ticket_reply); // SQL Escape Ticket Reply
// Update Ticket Status & updated at (in case status didn't change) // Update Ticket Status & updated at (in case status didn't change)
mysqli_query($mysqli, "UPDATE tickets SET ticket_status = $ticket_status, ticket_updated_at = NOW() WHERE ticket_id = $ticket_id"); mysqli_query($mysqli, "UPDATE tickets SET ticket_status = $ticket_status, ticket_updated_at = NOW() WHERE ticket_id = $ticket_id");
@@ -2231,387 +2258,6 @@ if (isset($_POST['export_tickets_csv'])) {
} }
if (isset($_POST['add_recurring_ticket'])) {
enforceUserPermission('module_support', 2);
require_once 'ticket_recurring_model.php';
$start_date = sanitizeInput($_POST['start_date']);
mysqli_query($mysqli, "INSERT INTO recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_start_date = '$start_date', recurring_ticket_next_run = '$start_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_created_by = $session_user_id, recurring_ticket_client_id = $client_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_asset_id = $asset_id, recurring_ticket_category = $category");
$recurring_ticket_id = mysqli_insert_id($mysqli);
// Add Additional Assets
if (isset($_POST['additional_assets'])) {
foreach ($_POST['additional_assets'] as $additional_asset) {
$additional_asset_id = intval($additional_asset);
mysqli_query($mysqli, "INSERT INTO recurring_ticket_assets SET recurring_ticket_id = $recurring_ticket_id, asset_id = $additional_asset_id");
}
}
logAction("Recurring Ticket", "Create", "$session_name created recurring ticket for $subject - $frequency", $client_id, $recurring_ticket_id);
flash_alert("Recurring ticket <strong>$subject - $frequency</strong> created");
redirect();
}
if (isset($_POST['edit_recurring_ticket'])) {
enforceUserPermission('module_support', 2);
require_once 'ticket_recurring_model.php';
$recurring_ticket_id = intval($_POST['recurring_ticket_id']);
$next_run_date = sanitizeInput($_POST['next_date']);
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_subject = '$subject', recurring_ticket_details = '$details', recurring_ticket_priority = '$priority', recurring_ticket_frequency = '$frequency', recurring_ticket_billable = $billable, recurring_ticket_next_run = '$next_run_date', recurring_ticket_assigned_to = $assigned_to, recurring_ticket_asset_id = $asset_id, recurring_ticket_contact_id = $contact_id, recurring_ticket_category = $category WHERE recurring_ticket_id = $recurring_ticket_id");
// Add Additional Assets
if (isset($_POST['additional_assets'])) {
mysqli_query($mysqli, "DELETE FROM recurring_ticket_assets WHERE recurring_ticket_id = $recurring_ticket_id");
foreach ($_POST['additional_assets'] as $additional_asset) {
$additional_asset_id = intval($additional_asset);
mysqli_query($mysqli, "INSERT INTO recurring_ticket_assets SET recurring_ticket_id = $recurring_ticket_id, asset_id = $additional_asset_id");
}
}
logAction("Recurring Ticket", "Edit", "$session_name edited recurring ticket $subject", $client_id, $recurring_ticket_id);
flash_alert("Recurring ticket <strong>$subject - $frequency</strong> updated");
redirect();
}
if (isset($_POST['bulk_force_recurring_tickets'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_support', 2);
if (isset($_POST['recurring_ticket_ids'])) {
// Cycle through array and pop each recurring scheduled ticket
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
if (mysqli_num_rows($sql) > 0) {
$row = mysqli_fetch_array($sql);
$subject = sanitizeInput($row['recurring_ticket_subject']);
$details = mysqli_real_escape_string($mysqli, $row['recurring_ticket_details']);
$priority = sanitizeInput($row['recurring_ticket_priority']);
$frequency = sanitizeInput(strtolower($row['recurring_ticket_frequency']));
$billable = intval($row['recurring_ticket_billable']);
$old_next_recurring_date = sanitizeInput($row['recurring_ticket_next_run']);
$created_id = intval($row['recurring_ticket_created_by']);
$assigned_id = intval($row['recurring_ticket_assigned_to']);
$contact_id = intval($row['recurring_ticket_contact_id']);
$client_id = intval($row['recurring_ticket_client_id']);
$asset_id = intval($row['recurring_ticket_asset_id']);
$category = intval($row['recurring_ticket_category']);
$url_key = randomString(156);
$ticket_status = 1; // Default
if ($assigned_id > 0) {
$ticket_status = 2; // Set to open if we've auto-assigned an agent
}
// Sanitize Config Vars from get_settings.php and Session Vars from check_login.php
$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_base_url = sanitizeInput($config_base_url);
// Assign this new ticket the next ticket number & increment config_ticket_next_number by 1 (for the next ticket)
$ticket_number_sql = mysqli_fetch_array(mysqli_query($mysqli, "SELECT config_ticket_next_number FROM settings WHERE company_id = 1"));
$ticket_number = intval($ticket_number_sql['config_ticket_next_number']);
$new_config_ticket_next_number = $ticket_number + 1;
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
// Raise the ticket
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Recurring', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = '$ticket_status', ticket_billable = $billable, ticket_url_key = '$url_key', ticket_created_by = $created_id, ticket_assigned_to = $assigned_id, ticket_contact_id = $contact_id, ticket_client_id = $client_id, ticket_asset_id = $asset_id, ticket_category = $category, ticket_recurring_ticket_id = $recurring_ticket_id");
$id = mysqli_insert_id($mysqli);
// Copy Additional Assets from Recurring ticket to new ticket
mysqli_query($mysqli, "INSERT INTO ticket_assets (ticket_id, asset_id)
SELECT $id, asset_id
FROM recurring_ticket_assets
WHERE recurring_ticket_id = $recurring_ticket_id");
// Notifications
customAction('ticket_create', $id);
// Get client/contact/ticket details
$sql = mysqli_query(
$mysqli,
"SELECT client_name, contact_name, contact_email, ticket_prefix, ticket_number, ticket_priority, ticket_subject, ticket_details FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
WHERE ticket_id = $id"
);
$row = mysqli_fetch_array($sql);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_priority = sanitizeInput($row['ticket_priority']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_details = mysqli_real_escape_string($mysqli, $row['ticket_details']);
$data = [];
// Notify client by email their ticket has been raised, if general notifications are turned on & there is a valid contact email
if (!empty($config_smtp_host) && $config_ticket_client_general_notifications == 1 && filter_var($contact_email, FILTER_VALIDATE_EMAIL)) {
$email_subject = "Ticket created - [$ticket_prefix$ticket_number] - $ticket_subject (scheduled)";
$email_body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>A ticket regarding \"$ticket_subject\" has been automatically created for you.<br><br>--------------------------------<br>$ticket_details--------------------------------<br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: Open<br>Portal: https://$config_base_url/client/ticket.php?id=$id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$email = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $email_subject,
'body' => $email_body
];
$data[] = $email;
}
// Add to the mail queue
addToMailQueue($data);
// Set the next run date (based on the scheduled date, rather than now, so things keep their schedule)
$dt_old_next_recurring_date = new DateTime($old_next_recurring_date);
if ($frequency == "weekly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 week'));
} elseif ($frequency == "monthly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 month'));
} elseif ($frequency == "quarterly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('3 months'));
} elseif ($frequency == "biannually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('6 months'));
} elseif ($frequency == "annually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('12 months'));
}
// Update the run date
$next_run = $next_run->format('Y-m-d');
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_next_run = '$next_run' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Ticket", "Create", "$session_name force created recurring scheduled $frequency ticket - $config_ticket_prefix$ticket_number - $subject", $client_id, $id);
}
}
flash_alert("$count Recurring Tickets Forced");
}
redirect();
}
if (isset($_GET['force_recurring_ticket'])) {
validateCSRFToken($_GET['csrf_token']);
enforceUserPermission('module_support', 2);
$recurring_ticket_id = intval($_GET['force_recurring_ticket']);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
if (mysqli_num_rows($sql) > 0) {
$row = mysqli_fetch_array($sql);
$subject = sanitizeInput($row['recurring_ticket_subject']);
$details = mysqli_real_escape_string($mysqli, $row['recurring_ticket_details']);
$priority = sanitizeInput($row['recurring_ticket_priority']);
$frequency = sanitizeInput(strtolower($row['recurring_ticket_frequency']));
$billable = intval($row['recurring_ticket_billable']);
$old_next_recurring_date = sanitizeInput($row['recurring_ticket_next_run']);
$created_id = intval($row['recurring_ticket_created_by']);
$assigned_id = intval($row['recurring_ticket_assigned_to']);
$contact_id = intval($row['recurring_ticket_contact_id']);
$client_id = intval($row['recurring_ticket_client_id']);
$asset_id = intval($row['recurring_ticket_asset_id']);
$category = intval($row['recurring_ticket_category']);
$url_key = randomString(156);
$ticket_status = 1; // Default
if ($assigned_id > 0) {
$ticket_status = 2; // Set to open if we've auto-assigned an agent
}
// Sanitize Config Vars from get_settings.php and Session Vars from check_login.php
$config_ticket_prefix = sanitizeInput($config_ticket_prefix);
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_base_url = sanitizeInput($config_base_url);
// Assign this new ticket the next ticket number & increment config_ticket_next_number by 1 (for the next ticket)
$ticket_number = $config_ticket_next_number;
$new_config_ticket_next_number = $config_ticket_next_number + 1;
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
// Raise the ticket
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Recurring', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = '$ticket_status', ticket_billable = $billable, ticket_url_key = '$url_key', ticket_created_by = $created_id, ticket_assigned_to = $assigned_id, ticket_contact_id = $contact_id, ticket_client_id = $client_id, ticket_asset_id = $asset_id, ticket_category = $category, ticket_recurring_ticket_id = $recurring_ticket_id");
$id = mysqli_insert_id($mysqli);
// Copy Additional Assets from Recurring ticket to new ticket
mysqli_query($mysqli, "INSERT INTO ticket_assets (ticket_id, asset_id)
SELECT $id, asset_id
FROM recurring_ticket_assets
WHERE recurring_ticket_id = $recurring_ticket_id");
// Notifications
customAction('ticket_create', $id);
// Get client/contact/ticket details
$sql = mysqli_query(
$mysqli,
"SELECT client_name, contact_name, contact_email, ticket_prefix, ticket_number, ticket_priority, ticket_subject, ticket_details FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
WHERE ticket_id = $id"
);
$row = mysqli_fetch_array($sql);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$client_name = sanitizeInput($row['client_name']);
$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_priority = sanitizeInput($row['ticket_priority']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_details = mysqli_real_escape_string($mysqli, $row['ticket_details']);
$data = [];
// Notify client by email their ticket has been raised, if general notifications are turned on & there is a valid contact email
if (!empty($config_smtp_host) && $config_ticket_client_general_notifications == 1 && filter_var($contact_email, FILTER_VALIDATE_EMAIL)) {
$email_subject = "Ticket created - [$ticket_prefix$ticket_number] - $ticket_subject (scheduled)";
$email_body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello $contact_name,<br><br>A ticket regarding \"$ticket_subject\" has been automatically created for you.<br><br>--------------------------------<br>$ticket_details--------------------------------<br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: Open<br>Portal: https://$config_base_url/client/ticket.php?id=$id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$email = [
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $email_subject,
'body' => $email_body
];
$data[] = $email;
}
// Add to the mail queue
addToMailQueue($data);
// Set the next run date (based on the scheduled date, rather than now, so things keep their schedule)
$dt_old_next_recurring_date = new DateTime($old_next_recurring_date);
if ($frequency == "weekly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 week'));
} elseif ($frequency == "monthly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('1 month'));
} elseif ($frequency == "quarterly") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('3 months'));
} elseif ($frequency == "biannually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('6 months'));
} elseif ($frequency == "annually") {
$next_run = date_add($dt_old_next_recurring_date, date_interval_create_from_date_string('12 months'));
}
// Update the run date
$next_run = $next_run->format('Y-m-d');
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_next_run = '$next_run' WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Ticket", "Create", "$session_name force created recurring scheduled $frequency ticket - $config_ticket_prefix$ticket_number - $subject", $client_id, $id);
flash_alert("Recurring Ticket Forced");
redirect();
} else {
flash_alert("Recurring Ticket Force failed", 'error');
redirect();
}
}
if (isset($_GET['delete_recurring_ticket'])) {
validateCSRFToken($_GET['csrf_token']);
enforceUserPermission('module_support', 3);
$recurring_ticket_id = intval($_GET['delete_recurring_ticket']);
// Get Scheduled Ticket Subject Ticket Prefix, Number and Client ID for logging and alert message
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
$row = mysqli_fetch_array($sql);
$subject = sanitizeInput($row['recurring_ticket_subject']);
$frequency = sanitizeInput($row['recurring_ticket_frequency']);
$client_id = intval($row['recurring_ticket_client_id']);
// Delete
mysqli_query($mysqli, "DELETE FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Delete", "$session_name deleted recurring ticket $subject", $client_id, $recurring_ticket_id);
flash_alert("Recurring ticket <strong>$subject - $frequency</strong> deleted", 'error');
redirect();
}
if (isset($_POST['bulk_delete_recurring_tickets'])) {
validateCSRFToken($_POST['csrf_token']);
enforceUserPermission('module_support', 3);
if (isset($_POST['recurring_ticket_ids'])) {
$count = count($_POST['recurring_ticket_ids']);
// Cycle through array and delete each recurring scheduled ticket
foreach ($_POST['recurring_ticket_ids'] as $recurring_ticket_id) {
$recurring_ticket_id = intval($recurring_ticket_id);
mysqli_query($mysqli, "DELETE FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id");
logAction("Recurring Ticket", "Delete", "$session_name deleted recurring ticket", 0, $recurring_ticket_id);
}
logAction("Recurring Ticket", "Bulk Delete", "$session_name deleted $count recurring ticket(s)");
flash_alert("Deleted <strong>$count</strong> recurring ticket(s)", 'error');
}
redirect();
}
if (isset($_POST['edit_ticket_billable_status'])) { if (isset($_POST['edit_ticket_billable_status'])) {
enforceUserPermission('module_support', 2); enforceUserPermission('module_support', 2);

View File

@@ -94,34 +94,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -75,34 +75,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -51,34 +51,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="col-sm-8"> <div class="col-sm-8">
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -76,34 +76,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,7 @@
<?php <?php
// Default Column Sortby Filter // Default Column Sortby Filter
$sort = "recurring_ticket_subject"; $sort = "recurring_ticket_next_run";
$order = "ASC"; $order = "ASC";
// If client_id is in URI then show client Side Bar and client header // If client_id is in URI then show client Side Bar and client header
@@ -18,14 +18,38 @@ if (isset($_GET['client_id'])) {
// Perms // Perms
enforceUserPermission('module_support'); enforceUserPermission('module_support');
// Ticket client access snippet // Category Filter
$rec_ticket_permission_snippet = ''; if (isset($_GET['category']) & !empty($_GET['category'])) {
if (!empty($client_access_string)) { $category_query = 'AND (category_id = ' . intval($_GET['category']) . ')';
$rec_ticket_permission_snippet = "AND recurring_ticket_client_id IN ($client_access_string)"; $category_filter = intval($_GET['category']);
} else {
// Default - any
$category_query = '';
$category_filter = '';
} }
//Rebuild URL // Assigned Agent Filter
$url_query_strings_sort = http_build_query($get_copy); if (isset($_GET['assigned_agent']) & !empty($_GET['assigned_agent'])) {
$assigned_agent_query = 'AND (user_id = ' . intval($_GET['assigned_agent']) . ')';
$assigned_agent_filter = intval($_GET['assigned_agent']);
} else {
// Default - any
$assigned_agent_query = '';
$assigned_agent_filter = '';
}
// Billable Filter
if (isset($_GET['billable']) && $_GET['billable'] == 1) {
$billable_query = 'AND (recurring_ticket_billable = 1)';
$billable_filter = 1;
} elseif (isset($_GET['billable']) && $_GET['billable'] == 0) {
$billable_query = 'AND (recurring_ticket_billable = 0)';
$billable_filter = 0;
} else {
// Default - any
$billable_query = '';
$billable_filter = '';
}
// SQL // SQL
$sql = mysqli_query( $sql = mysqli_query(
@@ -35,7 +59,10 @@ $sql = mysqli_query(
LEFT JOIN categories ON category_id = recurring_ticket_category LEFT JOIN categories ON category_id = recurring_ticket_category
LEFT JOIN users ON user_id = recurring_ticket_assigned_to LEFT JOIN users ON user_id = recurring_ticket_assigned_to
WHERE (recurring_tickets.recurring_ticket_subject LIKE '%$q%' OR category_name LIKE '%$q%') WHERE (recurring_tickets.recurring_ticket_subject LIKE '%$q%' OR category_name LIKE '%$q%')
$rec_ticket_permission_snippet $access_permission_query
$category_query
$assigned_agent_query
$billable_query
$client_query $client_query
ORDER BY ORDER BY
CASE CASE
@@ -72,7 +99,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<form autocomplete="off"> <form autocomplete="off">
<?php if ($client_url) { ?> <?php if ($client_url) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>"> <input type="hidden" name="client_id" value="<?= $client_id ?>">
<?php } ?> <?php } ?>
<div class="row"> <div class="row">
@@ -84,7 +111,54 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-8"> <div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="category" onchange="this.form.submit()">
<option value="">- All Categories -</option>
<?php
$sql_categories_filter = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND EXISTS (SELECT 1 FROM recurring_tickets WHERE recurring_ticket_category = category_id $client_query) ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_categories_filter)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
?>
<option <?php if ($category_filter == $category_id) { echo "selected"; } ?> value="<?= $category_id ?>"><?= $category_name ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="assigned_agent" onchange="this.form.submit()">
<option value="">- All Agents -</option>
<?php
$sql_assigned_agents_filter = mysqli_query($mysqli, "SELECT user_id, user_name FROM users WHERE user_type = 1 AND EXISTS (SELECT 1 FROM recurring_tickets WHERE recurring_ticket_assigned_to = user_id $client_query) ORDER BY user_name ASC");
while ($row = mysqli_fetch_array($sql_assigned_agents_filter)) {
$user_id = intval($row['user_id']);
$user_name = nullable_htmlentities($row['user_name']);
?>
<option <?php if ($assigned_agent_filter == $user_id) { echo "selected"; } ?> value="<?= $user_id ?>"><?= $user_name ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="billable" onchange="this.form.submit()">
<option value="">- Billable Status -</option>
<option <?php if ($billable_filter == 1) { echo "selected"; } ?> value="1">Billable</option>
<option <?php if ($billable_filter == 0) { echo "selected"; } ?> value="0">Non-Billable</option>
</select>
</div>
</div>
<div class="col-md-2">
<?php if (lookupUserPermission("module_support") >= 2) { ?> <?php if (lookupUserPermission("module_support") >= 2) { ?>
<div class="dropdown float-right" id="bulkActionButton" hidden> <div class="dropdown float-right" id="bulkActionButton" hidden>
@@ -93,9 +167,29 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<button class="dropdown-item" type="submit" form="bulkActions" name="bulk_force_recurring_tickets"> <button class="dropdown-item" type="submit" form="bulkActions" name="bulk_force_recurring_tickets">
<i class="fa fa-fw fa-paper-plane text-secondary mr-2"></i>Force Reoccur <i class="fas fa-fw fa-paper-plane mr-2"></i>Force Reoccur
</button> </button>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignAgentRecurringTicketModal">
<i class="fas fa-fw fa-user-check mr-2"></i>Assign Agent
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditCategoryRecurringTicketModal">
<i class="fas fa-fw fa-layer-group mr-2"></i>Set Category
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditPriorityRecurringTicketModal">
<i class="fas fa-fw fa-thermometer-half mr-2"></i>Set Priority
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditBillableRecurringTicketModal">
<i class="fas fa-fw fa-dollar-sign mr-2"></i>Set Billable
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditNextRunRecurringTicketModal">
<i class="fas fa-fw fa-calendar-day mr-2"></i>Set Next Run Date
</a>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold" type="submit" form="bulkActions" name="bulk_delete_recurring_tickets"> <button class="dropdown-item text-danger text-bold" type="submit" form="bulkActions" name="bulk_delete_recurring_tickets">
<i class="fas fa-fw fa-trash mr-2"></i>Delete <i class="fas fa-fw fa-trash mr-2"></i>Delete
</button> </button>
@@ -121,13 +215,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)"> <input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)">
</div> </div>
</td> </td>
<?php if (!$client_url) { ?>
<th> <th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>"> <a class="text-secondary" href="?<?= $url_query_strings_sort ?>&sort=recurring_ticket_next_run&order=<?= $disp ?>">
Client <?php if ($sort == 'client_name') { echo $order_icon; } ?> Next Run Date <?php if ($sort == 'recurring_ticket_next_run') { echo $order_icon; } ?>
</a> </a>
</th> </th>
<?php } ?>
<th> <th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=recurring_ticket_subject&order=<?php echo $disp; ?>"> <a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=recurring_ticket_subject&order=<?php echo $disp; ?>">
Subject <?php if ($sort == 'recurring_ticket_subject') { echo $order_icon; } ?> Subject <?php if ($sort == 'recurring_ticket_subject') { echo $order_icon; } ?>
@@ -148,16 +240,24 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
Frequency <?php if ($sort == 'recurring_ticket_frequency') { echo $order_icon; } ?> Frequency <?php if ($sort == 'recurring_ticket_frequency') { echo $order_icon; } ?>
</a> </a>
</th> </th>
<th class="text-center">
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=recurring_ticket_billable&order=<?php echo $disp; ?>">
Billable <?php if ($sort == 'recurring_ticket_billable') { echo $order_icon; } ?>
</a>
</th>
<th> <th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=user_name&order=<?php echo $disp; ?>"> <a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=user_name&order=<?php echo $disp; ?>">
Assigned <?php if ($sort == 'user_name') { echo $order_icon; } ?> Agent <?php if ($sort == 'user_name') { echo $order_icon; } ?>
</a> </a>
</th> </th>
<?php if (!$client_url) { ?>
<th> <th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=recurring_ticket_next_run&order=<?php echo $disp; ?>"> <a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
Next Run Date <?php if ($sort == 'recurring_ticket_next_run') { echo $order_icon; } ?> Client <?php if ($sort == 'client_name') { echo $order_icon; } ?>
</a> </a>
</th> </th>
<?php } ?>
<?php if (lookupUserPermission("module_support") >= 2) { ?> <?php if (lookupUserPermission("module_support") >= 2) { ?>
<th class="text-center">Action</th> <th class="text-center">Action</th>
<?php } ?> <?php } ?>
@@ -175,6 +275,12 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']); $recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']); $recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']); $recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
$recurring_ticket_billable = intval($row['recurring_ticket_billable']);
if ($recurring_ticket_billable) {
$recurring_ticket_billable_display = "<i class='fas fa-fw fa-check text-success'></i>";
} else {
$recurring_ticket_billable_display = "-";
}
$recurring_ticket_category = getFallBack(nullable_htmlentities($row['category_name'])); $recurring_ticket_category = getFallBack(nullable_htmlentities($row['category_name']));
$recurring_ticket_client_name = nullable_htmlentities($row['client_name']); $recurring_ticket_client_name = nullable_htmlentities($row['client_name']);
$assigned_to = getFallBack(nullable_htmlentities($row['user_name'])); $assigned_to = getFallBack(nullable_htmlentities($row['user_name']));
@@ -183,27 +289,26 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<tr> <tr>
<td class="pr-0"> <td class="pr-0">
<div class="form-check"> <div class="form-check">
<input class="form-check-input bulk-select" type="checkbox" name="recurring_ticket_ids[]" value="<?php echo $recurring_ticket_id ?>"> <input class="form-check-input bulk-select" type="checkbox" name="recurring_ticket_ids[]" value="<?= $recurring_ticket_id ?>">
</div> </div>
</td> </td>
<td class="text-bold"><?= $recurring_ticket_next_run ?></td>
<?php if (!$client_url) { ?>
<th><a href="recurring_tickets.php?client_id=<?php echo $recurring_ticket_client_id; ?>"><?php echo $recurring_ticket_client_name ?></a>
</th>
<?php } ?>
<td> <td>
<a class="ajax-modal" href="#" <a class="ajax-modal" href="#"
data-modal-size="lg" data-modal-size="lg"
data-modal-url="modals/recurring_ticket/recurring_ticket_edit.php?id=<?= $recurring_ticket_id ?>"> data-modal-url="modals/recurring_ticket/recurring_ticket_edit.php?id=<?= $recurring_ticket_id ?>">
<?php echo $recurring_ticket_subject ?> <?= $recurring_ticket_subject ?>
</a> </a>
</td> </td>
<td><?php echo $recurring_ticket_category ?></td> <td><?= $recurring_ticket_category ?></td>
<td><?php echo $recurring_ticket_priority ?></td> <td><?= $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td> <td><?= $recurring_ticket_frequency ?></td>
<td><?php echo $assigned_to ?></td> <td class="text-center"><?= $recurring_ticket_billable_display ?></td>
<td class="text-bold"><?php echo $recurring_ticket_next_run ?></td> <td><?= $assigned_to ?></td>
<?php if (!$client_url) { ?>
<th><a href="recurring_tickets.php?client_id=<?= $recurring_ticket_client_id ?>"><?= $recurring_ticket_client_name ?></a>
</th>
<?php } ?>
<?php if (lookupUserPermission("module_support") >= 2) { ?> <?php if (lookupUserPermission("module_support") >= 2) { ?>
<td> <td>
@@ -218,12 +323,12 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<i class="fas fa-fw fa-edit mr-2"></i>Edit <i class="fas fa-fw fa-edit mr-2"></i>Edit
</a> </a>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $recurring_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"> <a class="dropdown-item" href="post.php?force_recurring_ticket=<?= $recurring_ticket_id ?>&csrf_token=<?= $_SESSION['csrf_token'] ?>">
<i class="fa fa-fw fa-paper-plane text-secondary mr-2"></i>Force Reoccur <i class="fa fa-fw fa-paper-plane text-secondary mr-2"></i>Force Reoccur
</a> </a>
<?php if (lookupUserPermission("module_support") == 3) { ?> <?php if (lookupUserPermission("module_support") == 3) { ?>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?php echo $recurring_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"> <a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?= $recurring_ticket_id ?>&csrf_token=<?= $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete <i class="fas fa-fw fa-trash mr-2"></i>Delete
</a> </a>
<?php } ?> <?php } ?>
@@ -239,6 +344,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody> </tbody>
</table> </table>
<?php
require_once "modals/recurring_ticket/recurring_ticket_bulk_agent_edit.php";
require_once "modals/recurring_ticket/recurring_ticket_bulk_billable_edit.php";
require_once "modals/recurring_ticket/recurring_ticket_bulk_category_edit.php";
require_once "modals/recurring_ticket/recurring_ticket_bulk_next_run_edit.php";
require_once "modals/recurring_ticket/recurring_ticket_bulk_priority_edit.php";
?>
</form> </form>

View File

@@ -1,17 +1,17 @@
<?php <?php
require_once "../../config.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once "../../functions.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once "../../includes/check_login.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once "../../includes/page_title.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
// Reporting Perms // Reporting Perms
enforceUserPermission('module_reporting'); enforceUserPermission('module_reporting');
require_once "../../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once "../../includes/top_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once "includes/reports_side_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/agent/reports/includes/reports_side_nav.php';
require_once "../../includes/inc_wrapper.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once "../../includes/inc_alert_feedback.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once "../../includes/filter_header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
// Set variable default values // Set variable default values
$largest_income_month = 0; $largest_income_month = 0;

View File

@@ -1,7 +1,7 @@
<!-- Main Sidebar Container --> <!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-primary d-print-none"> <aside class="main-sidebar sidebar-dark-primary d-print-none">
<a class="pb-1 mt-1 brand-link" href="../<?php echo $config_start_page ?>"> <a class="pb-1 mt-1 brand-link" href="/agent/<?php echo $config_start_page ?>">
<p class="h5"><i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i> <p class="h5"><i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
<span class="brand-text ">Back | <strong>Reports</strong> <span class="brand-text ">Back | <strong>Reports</strong>
</p> </p>
@@ -18,55 +18,55 @@
<li class="nav-header">FINANCIAL</li> <li class="nav-header">FINANCIAL</li>
<?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_financial") >= 1) { ?> <?php if ($config_module_enable_accounting == 1 && lookupUserPermission("module_financial") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="income_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "income_summary.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="far fa-circle nav-icon"></i>
<p>Income</p> <p>Income</p>
</a> </a>
</li> </li>
<li class="nav-item"> <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"; } ?>"> <a href="/agent/reports/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> <i class="far fa-user nav-icon"></i>
<p>Income By Client</p> <p>Income By Client</p>
</a> </a>
</li> </li>
<li class="nav-item"> <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"; } ?>"> <a href="/agent/reports/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> <i class="fa fa-sync nav-icon"></i>
<p>Recurring Income By Client</p> <p>Recurring Income By Client</p>
</a> </a>
</li> </li>
<li class="nav-item"> <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"; } ?>"> <a href="/agent/reports/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> <i class="fa fa-exclamation-triangle nav-icon"></i>
<p>Clients with a Balance</p> <p>Clients with a Balance</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="expense_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "expense_summary.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="far fa-credit-card nav-icon"></i>
<p>Expense</p> <p>Expense</p>
</a> </a>
</li> </li>
<li class="nav-item"> <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"; } ?>"> <a href="/agent/reports/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> <i class="far fa-building nav-icon"></i>
<p>Expense By Vendor</p> <p>Expense By Vendor</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="tax_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tax_summary.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="fas fa-percent nav-icon"></i>
<p>Tax Summary</p> <p>Tax Summary</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="profit_loss.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "profit_loss.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="fas fa-file-invoice-dollar nav-icon"></i>
<p>Profit & Loss</p> <p>Profit & Loss</p>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="tickets_unbilled.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "tickets_unbilled.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="nav-icon fas fa-life-ring"></i>
<p>Unbilled Tickets</p> <p>Unbilled Tickets</p>
</a> </a>
@@ -78,21 +78,21 @@
<li class="nav-header">TECHNICAL</li> <li class="nav-header">TECHNICAL</li>
<?php if ($config_module_enable_ticketing && lookupUserPermission("module_support") >= 1) { ?> <?php if ($config_module_enable_ticketing && lookupUserPermission("module_support") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="ticket_summary.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "ticket_summary.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="nav-icon fas fa-life-ring"></i>
<p>Tickets</p> <p>Tickets</p>
</a> </a>
</li> </li>
<li class="nav-item"> <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"; } ?>"> <a href="/agent/reports/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> <i class="nav-icon fas fa-life-ring"></i>
<p>Tickets by Client</p> <p>Tickets by Client</p>
</a> </a>
</li> </li>
<li class="nav-item"> <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"; } ?>"> <a href="/agent/reports/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> <i class="nav-icon fas fa-life-ring"></i>
<p>Time by Technician</p> <p>Time by Technician</p>
</a> </a>
@@ -100,7 +100,7 @@
<?php } ?> <?php } ?>
<?php if (lookupUserPermission("module_credential") >= 1) { ?> <?php if (lookupUserPermission("module_credential") >= 1) { ?>
<li class="nav-item"> <li class="nav-item">
<a href="credential_rotation.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "credential_rotation.php") { echo "active"; } ?>"> <a href="/agent/reports/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> <i class="nav-icon fas fa-key"></i>
<p>Credential rotation</p> <p>Credential rotation</p>
</a> </a>

View File

@@ -46,34 +46,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -620,7 +620,6 @@ if (isset($_GET['ticket_id'])) {
<textarea <textarea
class="form-control tinymceTicket" name="ticket_reply" class="form-control tinymceTicket" name="ticket_reply"
placeholder="Type a response"> placeholder="Type a response">
<?php echo nl2br(getFieldById('user_settings',$session_user_id,'user_config_signature','html')); ?>
</textarea> </textarea>
</div> </div>
@@ -1227,9 +1226,9 @@ if (isset($_GET['ticket_id'])) {
<h5 class="card-title"><i class="fas fa-fw fa-project-diagram mr-2 mt-2"></i>Project</h5> <h5 class="card-title"><i class="fas fa-fw fa-project-diagram mr-2 mt-2"></i>Project</h5>
<div class="card-tools"> <div class="card-tools">
<?php if (empty($ticket_resolved_at) && lookupUserPermission("module_support") >= 2) { ?> <?php if (empty($ticket_resolved_at) && lookupUserPermission("module_support") >= 2) { ?>
<a class="btn btn-light text-secondary btn-sm" href="#"> <button type="button" class="btn btn-light text-secondary btn-sm ajax-modal" data-modal-url="modals/ticket/ticket_edit_project.php?id=<?= $ticket_id ?>">
<i class="fas fa-edit"></i> <i class="fas fa-edit"></i>
</a> </button>
<?php } ?> <?php } ?>
</div> </div>
</div> </div>

View File

@@ -9,7 +9,7 @@
<tr> <tr>
<td> <td>
<?php if (isset($_GET['status']) && $_GET['status'] !== 'Closed') { ?> <?php if ($status !== 'Closed') { ?>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)" onkeydown="checkAll(this)"> <input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)" onkeydown="checkAll(this)">
</div> </div>

View File

@@ -306,9 +306,7 @@ $sql_categories_filter = mysqli_query(
<div <div
class="collapse mt-3 class="collapse mt-3
<?php <?php
if ( if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01'
!empty($_GET['dtf'])
|| (isset($_GET['canned_date']) && $_GET['canned_date'] !== "custom")
|| (isset($_GET['status']) && is_array($_GET['status']) || (isset($_GET['status']) && is_array($_GET['status'])
|| (isset($_GET['assigned']) && $_GET['assigned'] || (isset($_GET['assigned']) && $_GET['assigned']
))) )))
@@ -317,59 +315,13 @@ $sql_categories_filter = mysqli_query(
id="advancedFilter" id="advancedFilter"
> >
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
echo "selected"; <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
} ?> value="custom">Custom <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
</option>
<option <?php if ($_GET['canned_date'] == "today") {
echo "selected";
} ?> value="today">Today
</option>
<option <?php if ($_GET['canned_date'] == "yesterday") {
echo "selected";
} ?> value="yesterday">Yesterday
</option>
<option <?php if ($_GET['canned_date'] == "thisweek") {
echo "selected";
} ?> value="thisweek">This Week
</option>
<option <?php if ($_GET['canned_date'] == "lastweek") {
echo "selected";
} ?> value="lastweek">Last Week
</option>
<option <?php if ($_GET['canned_date'] == "thismonth") {
echo "selected";
} ?> value="thismonth">This Month
</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") {
echo "selected";
} ?> value="lastmonth">Last Month
</option>
<option <?php if ($_GET['canned_date'] == "thisyear") {
echo "selected";
} ?> value="thisyear">This Year
</option>
<option <?php if ($_GET['canned_date'] == "lastyear") {
echo "selected";
} ?> value="lastyear">Last Year
</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
<div class="col-md-3"> <div class="col-md-3">

View File

@@ -69,34 +69,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" || $account_from_filter || $account_to_filter ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01' || $account_from_filter || $account_to_filter ) { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">

View File

@@ -70,34 +70,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div> </div>
</div> </div>
</div> </div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter"> <div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-3">
<div class="form-group"> <div class="form-group">
<label>Canned Date</label> <label>Date range</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date"> <input type="text" id="dateFilter" class="form-control" autocomplete="off">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option> <input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option> <input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option> <input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,13 +1,12 @@
<?php <?php
require_once "../../config.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
require_once "../../functions.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
require_once "../../includes/check_login.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
require_once "../../includes/page_title.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/page_title.php';
require_once "../../includes/header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
require_once "../../includes/top_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
require_once "includes/user_side_nav.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/agent/user/includes/user_side_nav.php';
require_once "../../includes/inc_wrapper.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
require_once "../../includes/inc_alert_feedback.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
require_once "../../includes/filter_header.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';

View File

@@ -1,7 +1,7 @@
<!-- Main Sidebar Container --> <!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none"> <aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none">
<a class="brand-link pb-1 mt-1" href="../<?php echo $config_start_page ?>"> <a class="brand-link pb-1 mt-1" href="/agent/<?php echo $config_start_page ?>">
<p class="h5"> <p class="h5">
<i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i> <i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
<span class="brand-text"> <span class="brand-text">
@@ -19,28 +19,28 @@
<ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" role="menu" data-accordion="false"> <ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" role="menu" data-accordion="false">
<li class="nav-item"> <li class="nav-item">
<a href="user_details.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_details.php") { echo "active"; } ?>"> <a href="/agent/user/user_details.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_details.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-user"></i> <i class="nav-icon fas fa-user"></i>
<p>Details</p> <p>Details</p>
</a> </a>
</li> </li>
<li class="nav-item mt-2"> <li class="nav-item mt-2">
<a href="user_security.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_security.php") { echo "active"; } ?>"> <a href="/agent/user/user_security.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_security.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-shield-alt"></i> <i class="nav-icon fas fa-shield-alt"></i>
<p>Security</p> <p>Security</p>
</a> </a>
</li> </li>
<li class="nav-item mt-2"> <li class="nav-item mt-2">
<a href="user_preferences.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_preferences.php") { echo "active"; } ?>"> <a href="/agent/user/user_preferences.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_preferences.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-cogs"></i> <i class="nav-icon fas fa-cogs"></i>
<p>Preferences</p> <p>Preferences</p>
</a> </a>
</li> </li>
<li class="nav-item mt-2"> <li class="nav-item mt-2">
<a href="user_activity.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_activity.php") { echo "active"; } ?>"> <a href="/agent/user/user_activity.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "user_activity.php") { echo "active"; } ?>">
<i class="nav-icon fas fa-clock"></i> <i class="nav-icon fas fa-clock"></i>
<p>Activity</p> <p>Activity</p>
</a> </a>

View File

@@ -12,7 +12,7 @@ if (isset($_POST['edit_your_user_details'])) {
$name = sanitizeInput($_POST['name']); $name = sanitizeInput($_POST['name']);
$email = sanitizeInput($_POST['email']); $email = sanitizeInput($_POST['email']);
$signature = sanitizeInput($_POST['signature']); $signature = mysqli_escape_string($mysqli,$_POST['signature']);
$existing_file_name = sanitizeInput(getFieldById('users', $session_user_id, 'user_avatar')); $existing_file_name = sanitizeInput(getFieldById('users', $session_user_id, 'user_avatar'));

View File

@@ -58,12 +58,8 @@ require_once "includes/inc_all_user.php";
<div class="form-group"> <div class="form-group">
<label>Signature</label> <label>Signature</label>
<div class="input-group"> <textarea class="form-control tinymceTicket" name="signature" rows="4" placeholder="Create a signature automatically appended to tickets, emails etc"><?php echo getFieldById('user_settings',$session_user_id,'user_config_signature','html'); ?>
<div class="input-group-prepend"> </textarea>
<span class="input-group-text"><i class="fa fa-fw fa-pen"></i></span>
</div>
<textarea class="form-control" name="signature" rows="4" placeholder="Create a signature automatically appended to tickets, emails etc"><?php echo getFieldById('user_settings',$session_user_id,'user_config_signature','html'); ?></textarea>
</div>
</div> </div>
<button type="submit" name="edit_your_user_details" class="btn btn-primary btn-responsive"><i class="fas fa-check mr-2"></i>Save</button> <button type="submit" name="edit_your_user_details" class="btn btn-primary btn-responsive"><i class="fas fa-check mr-2"></i>Save</button>

8
api/v1/custom/readme.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
/*
- Custom Pages -
If you wish to add custom pages to ITFlow, add them to this directory"
Link to Documentation for File Directory Structure and examples
*/

View File

@@ -16,18 +16,18 @@ if (!isset($_SESSION)) {
} }
if (!isset($_SESSION['client_logged_in']) || !$_SESSION['client_logged_in']) { if (!isset($_SESSION['client_logged_in']) || !$_SESSION['client_logged_in']) {
header("Location: login.php"); header("Location: /client/login.php");
die; die;
} }
// Check user type // Check user type
if ($_SESSION['user_type'] !== 2) { if ($_SESSION['user_type'] !== 2) {
header("Location: login.php"); header("Location: /client/login.php");
exit(); exit();
} }
// Set Timezone // Set Timezone
require_once "../includes/inc_set_timezone.php"; require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_set_timezone.php';
// User IP & UA // User IP & UA
$session_ip = sanitizeInput(getIP()); $session_ip = sanitizeInput(getIP());

View File

@@ -21,7 +21,7 @@
</p> </p>
<?php require_once "../includes/inc_confirm_modal.php"; ?> <?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_confirm_modal.php'; ?>
<!-- jQuery --> <!-- jQuery -->
<script src="/plugins/jquery/jquery.min.js"></script> <script src="/plugins/jquery/jquery.min.js"></script>

Some files were not shown because too many files have changed in this diff Show More