[Feature] Updated Invoice Ticket to include more details in the description, predefined along with optional Invoice Title, helper texts below qty and price to show how it gets its information, fixed ticket number not showing in ticket reply when adding ticket to an existing invoice. Add to Existing Invoice is default if open invoices exist, migrated many more ticket related modals to use ajax-modal

This commit is contained in:
johnnyq
2025-11-04 17:48:21 -05:00
parent 43a7b7faa5
commit 9fcaf9f5cc
19 changed files with 1014 additions and 913 deletions

View File

@@ -1,41 +1,45 @@
<div class="modal" id="addCalendarModal" 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-plus mr-2"></i>New Calendar</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body">
<?php
<div class="form-group">
<label>Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Name your calendar" maxlength="200" required autofocus>
</div>
</div>
require_once '../../../includes/modal_header.php';
<div class="form-group">
<label>Color <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-paint-brush"></i></span>
</div>
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
ob_start();
</div>
<div class="modal-footer">
<button type="submit" name="add_calendar" class="btn btn-primary"><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>
</div>
</form>
</div>
</div>
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-calendar-plus mr-2"></i>New Calendar</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Name your calendar" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group">
<label>Color <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-paint-brush"></i></span>
</div>
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_calendar" class="btn btn-primary"><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>
</div>
</form>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -1,153 +1,160 @@
<div class="modal" id="addRackModal" 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-server mr-2"></i>New Rack</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<?php
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
require_once '../../../includes/modal_header.php';
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
$client_id = intval($_GET['client_id'] ?? 0);
<div class="modal-body">
ob_start();
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
</li>
</ul>
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-server mr-2"></i>New Rack</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<hr>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<div class="tab-content">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<div class="tab-pane fade show active" id="pills-details">
<div class="modal-body">
<div class="form-group">
<label>Name <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-server"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Rack name" maxlength="200" required autofocus>
</div>
</div>
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
</li>
</ul>
<div class="form-group">
<label>Description</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
</div>
<input type="text" class="form-control" name="description" placeholder="Description of the rack">
</div>
</div>
<hr>
<div class="form-group">
<label>Type <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-server"></i></span>
</div>
<select class="form-control select2" name="type" required>
<option value="">- Type -</option>
<?php foreach($rack_type_select_array as $rack_type) { ?>
<option><?php echo $rack_type; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="tab-content">
<div class="form-group">
<label>Model</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="make" placeholder="ex StarTech 12U Open Frame" maxlength="200">
</div>
</div>
<div class="form-group">
<label>Depth</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-ruler"></i></span>
</div>
<input type="text" class="form-control" name="depth" placeholder="Rack Depth eg 800 mm or 31.5 Inches" maxlength="50">
</div>
</div>
<div class="form-group">
<label>Number of Units <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-sort-numeric-up-alt"></i></span>
</div>
<input type="number" class="form-control" name="units" placeholder="Number of Units" min="1" max="70" required>
</div>
</div>
<div class="form-group">
<label>Physical Location</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
</div>
<input type="text" class="form-control" name="physical_location" placeholder="Physical location eg. Floor 2, Closet B" maxlength="200">
</div>
</div>
<div class="form-group">
<label>Location</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
</div>
<select class="form-control select2" name="location">
<option value="">- Location -</option>
<?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_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
?>
<option value="<?php echo $location_id; ?>"><?php echo $location_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="tab-pane fade show active" id="pills-details">
<div class="form-group">
<label>Name <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-server"></i></span>
</div>
<div class="tab-pane fade" id="pills-notes">
<div class="form-group">
<label>Upload Photo</label>
<input type="file" class="form-control-file" name="file" accept="image/*">
</div>
<div class="form-group">
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
</div>
</div>
<input type="text" class="form-control" name="name" placeholder="Rack name" maxlength="200" required autofocus>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_rack" 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>
<div class="form-group">
<label>Description</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
</div>
<input type="text" class="form-control" name="description" placeholder="Description of the rack">
</div>
</div>
</form>
<div class="form-group">
<label>Type <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-server"></i></span>
</div>
<select class="form-control select2" name="type" required>
<option value="">- Type -</option>
<?php foreach($rack_type_select_array as $rack_type) { ?>
<option><?php echo $rack_type; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Model</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="make" placeholder="ex StarTech 12U Open Frame" maxlength="200">
</div>
</div>
<div class="form-group">
<label>Depth</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-ruler"></i></span>
</div>
<input type="text" class="form-control" name="depth" placeholder="Rack Depth eg 800 mm or 31.5 Inches" maxlength="50">
</div>
</div>
<div class="form-group">
<label>Number of Units <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-sort-numeric-up-alt"></i></span>
</div>
<input type="number" class="form-control" name="units" placeholder="Number of Units" min="1" max="70" required>
</div>
</div>
<div class="form-group">
<label>Physical Location</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
</div>
<input type="text" class="form-control" name="physical_location" placeholder="Physical location eg. Floor 2, Closet B" maxlength="200">
</div>
</div>
<div class="form-group">
<label>Location</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
</div>
<select class="form-control select2" name="location">
<option value="">- Location -</option>
<?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_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
?>
<option value="<?php echo $location_id; ?>"><?php echo $location_name; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-notes">
<div class="form-group">
<label>Upload Photo</label>
<input type="file" class="form-control-file" name="file" accept="image/*">
</div>
<div class="form-group">
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_rack" 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>
</div>
</form>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -1,64 +1,68 @@
<div class="modal" id="addTicketWatcherModal" 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-eye mr-2"></i>Adding a ticket Watcher: <strong><?php echo "$ticket_prefix$ticket_number"; ?></strong> - <?php echo $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; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<input type="hidden" name="ticket_number" value="<?php echo "$ticket_prefix$ticket_number"; ?>">
<input type="hidden" name="watcher_notify" value="0"> <!-- Default 0 -->
<div class="modal-body">
<?php
<div class="form-group">
<label>Watcher Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<select class="form-control select2" data-tags="true" name="watcher_email">
<option value="">- Select a contact or enter an email(s) -</option>
<?php
require_once '../../../includes/modal_header.php';
$sql_client_contacts_select = mysqli_query($mysqli, "SELECT contact_id, contact_name, contact_email FROM contacts WHERE contact_client_id = $client_id AND contact_email <> '' ORDER BY contact_name ASC");
while ($row = mysqli_fetch_array($sql_client_contacts_select)) {
$contact_id_select = intval($row['contact_id']);
$contact_name_select = nullable_htmlentities($row['contact_name']);
$contact_email_select = nullable_htmlentities($row['contact_email']);
?>
<option value="<?php echo $contact_email_select; ?>"><?php echo "$contact_name_select - $contact_email_select"; ?></option>
$ticket_id = intval($_GET['ticket_id'] ?? 0);
$client_id = intval(getFieldById('tickets', $ticket_id, 'ticket_client_id') ?? 0);
<?php
}
?>
</select>
</div>
</div>
ob_start();
<?php if (!empty($config_smtp_host)) { ?>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="watcher_notify" value="1" id="checkNotifyWatcher">
<label class="form-check-label" for="checkNotifyWatcher">
Send email notification
</label>
</div>
</div>
<?php } ?>
</div>
<div class="modal-footer">
<button type="submit" name="add_ticket_watcher" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Add</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-eye mr-2"></i>Adding a ticket Watcher</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; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<div class="modal-body">
<div class="form-group">
<label>Watcher Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<select class="form-control select2" data-tags="true" name="watcher_email">
<option value="">- Select a contact or enter an email(s) -</option>
<?php
$sql_client_contacts_select = mysqli_query($mysqli, "SELECT contact_id, contact_name, contact_email FROM contacts WHERE contact_client_id = $client_id AND contact_email <> '' ORDER BY contact_name ASC");
while ($row = mysqli_fetch_array($sql_client_contacts_select)) {
$contact_id_select = intval($row['contact_id']);
$contact_name_select = nullable_htmlentities($row['contact_name']);
$contact_email_select = nullable_htmlentities($row['contact_email']);
?>
<option value="<?php echo $contact_email_select; ?>"><?php echo "$contact_name_select - $contact_email_select"; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php if (!empty($config_smtp_host)) { ?>
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" name="watcher_notify" value="1" id="checkNotifyWatcher">
<label class="form-check-label" for="checkNotifyWatcher">
Send email notification
</label>
</div>
</div>
<?php } ?>
</div>
<div class="modal-footer">
<button type="submit" name="add_ticket_watcher" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Add</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

@@ -1,49 +1,70 @@
<div class="modal" id="clientChangeTicketModal" tabindex="-1">
<div class="modal-dialog modal-md">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-people-carry mr-2"></i>Change <?php echo "$ticket_prefix$ticket_number"; ?> to another client</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">
<?php
require_once '../../../includes/modal_header.php';
<div class="form-group">
<label>New Client <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-users"></i></span>
</div>
<select class="form-control select2" name="new_client_id" id="changeClientSelect" required>
</select>
</div>
</div>
$ticket_id = intval($_GET['ticket_id']);
$current_client_id = intval(getFieldById('tickets', $ticket_id, 'ticket_client_id'));
$ticket_prefix = nullable_htmlentities(getFieldById('tickets', $ticket_id, 'ticket_prefix'));
$ticket_number = nullable_htmlentities(getFieldById('tickets', $ticket_id, 'ticket_number'));
<div class="form-group">
<label>New Contact</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<select class="form-control select2" name="new_contact_id" id="changeContactSelect">
</select>
</div>
</div>
ob_start();
?>
</div>
<div class="modal-footer">
<button type="submit" name="change_client_ticket" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Change</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
</div>
</div>
<div class="modal-header bg-dark">
<h5 class="modal-title">
<i class="fa fa-fw fa-people-carry mr-2"></i>
Change <?php echo "$ticket_prefix$ticket_number"; ?> to another client
</h5>
<button type="button" class="close text-white" data-dismiss="modal"><span>&times;</span></button>
</div>
<!-- Ticket Change Client JS -->
<link rel="stylesheet" href="../plugins/jquery-ui/jquery-ui.min.css">
<script src="../plugins/jquery-ui/jquery-ui.min.js"></script>
<script src="js/ticket_change_client.js"></script>
<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>New Client <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-users"></i></span>
</div>
<select class="form-control select2" name="new_client_id" id="client_select" required>
<?php
$sql_clients = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_lead = 0 AND client_archived_at IS NULL ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql_clients)) {
$client_id_select = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option value="<?= $client_id_select ?>" <?php if ($current_client_id == $client_id_select) echo 'selected'; ?>>
<?= $client_name ?>
</option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>New Contact</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<select class="form-control select2" name="new_contact_id" id="contact_select">
<option value="">- Select a contact -</option>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="change_client_ticket" class="btn btn-primary text-bold">
<i class="fa fa-check mr-2"></i>Change
</button>
<button type="button" class="btn btn-light" data-dismiss="modal">
<i class="fa fa-times mr-2"></i>Cancel
</button>
</div>
</form>
<script src="/agent/js/ticket_change_client.js"></script>
<?php require_once '../../../includes/modal_footer.php'; ?>

View File

@@ -1,49 +1,57 @@
<div class="modal" id="editTicketVendorModal<?php echo $ticket_id; ?>" 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-building mr-2"></i>Editing ticket Vendor: <strong><?php echo "$ticket_prefix$ticket_number"; ?></strong> - <?php echo $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">
<?php
<div class="form-group">
<label>Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="vendor">
<option value="0">- None -</option>
<?php
require_once '../../../includes/modal_header.php';
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);
?>
<option <?php if ($vendor_id == $vendor_id_select) { echo "selected"; } ?> value="<?php echo $vendor_id_select; ?>"><?php echo $vendor_name_select; ?></option>
$ticket_id = intval($_GET['ticket_id'] ?? 0);
<?php
}
?>
</select>
</div>
</div>
$client_id = intval(getFieldById('tickets', $ticket_id, 'ticket_client_id') ?? 0);
$vendor_id = intval(getFieldById('tickets', $ticket_id, 'ticket_vendor_id') ?? 0);
</div>
ob_start();
<div class="modal-footer">
<button type="submit" name="edit_ticket_vendor" 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>
</div>
</div>
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-building mr-2"></i>Editing ticket Vendor</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="<?= $ticket_id ?>">
<div class="modal-body">
<div class="form-group">
<label>Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="vendor">
<option value="0">- None -</option>
<?php
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
?>
<option <?php if ($vendor_id == $vendor_id_select) { echo "selected"; } ?> value="<?= $vendor_id_select ?>"><?= $vendor_name ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_ticket_vendor" 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

@@ -1,210 +1,322 @@
<?php
require_once '../../../includes/modal_header.php';
$ticket_id = intval($_GET['ticket_id']);
$ticket_sql = mysqli_query(
$mysqli,
"SELECT * FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
LEFT JOIN users ON ticket_assigned_to = user_id
LEFT JOIN locations ON ticket_location_id = location_id
LEFT JOIN assets ON ticket_asset_id = asset_id
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
LEFT JOIN categories ON ticket_category = category_id
WHERE ticket_id = $ticket_id
$access_permission_query
LIMIT 1"
);
$row = mysqli_fetch_array($ticket_sql);
$client_id = intval($row['client_id']);
$client_rate = floatval($row['client_rate']);
$ticket_prefix = nullable_htmlentities($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_category = intval($row['ticket_category']);
$ticket_category_display = nullable_htmlentities($row['category_name']);
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
$ticket_billable = intval($row['ticket_billable']);
$ticket_onsite = intval($row['ticket_onsite']);
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
$ticket_created_by = intval($row['ticket_created_by']);
$ticket_date = date('Y-m-d', strtotime($ticket_created_at));
$ticket_first_response_at = nullable_htmlentities($row['ticket_first_response_at']);
if ($ticket_first_response_at) {
$ticket_first_response_date_time = date('Y-m-d H:i', strtotime($ticket_first_response_at));
} else {
$ticket_first_response_date_time = '';
}
$ticket_resolved_at = nullable_htmlentities($row['ticket_resolved_at']);
if ($ticket_resolved_at) {
$ticket_resolved_date = date('Y-m-d', strtotime($ticket_resolved_at));
} else {
$ticket_resolved_date = '';
}
$ticket_assigned_to = intval($row['ticket_assigned_to']);
if ($ticket_assigned_to) {
$ticket_assigned_agent = nullable_htmlentities($row['user_name']);
} else {
$ticket_assigned_agent = '';
}
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$asset_id = intval($row['asset_id']);
$asset_name = nullable_htmlentities($row['asset_name']);
$asset_type = nullable_htmlentities($row['asset_type']);
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
$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 = formatPhoneNumber($row['location_phone']);
//Get Total Ticket Time
$ticket_total_reply_time = mysqli_query($mysqli, "SELECT SEC_TO_TIME(SUM(TIME_TO_SEC(ticket_reply_time_worked))) AS ticket_total_reply_time FROM ticket_replies WHERE ticket_reply_archived_at IS NULL AND ticket_reply_ticket_id = $ticket_id");
$row = mysqli_fetch_array($ticket_total_reply_time);
$ticket_total_reply_time = nullable_htmlentities($row['ticket_total_reply_time']);
$sql_invoices = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_status LIKE 'Draft' AND invoice_client_id = $client_id ORDER BY invoice_number ASC");
ob_start();
?>
<div class="modal" id="addInvoiceFromTicketModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-file-invoice-dollar mr-2"></i>Invoice ticket</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">
<?php if (mysqli_num_rows($sql_invoices) > 0) { ?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-file-invoice-dollar mr-2"></i>Invoice ticket</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">
<?php if (mysqli_num_rows($sql_invoices) > 0) { ?>
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-create-invoice"><i class="fa fa-fw fa-check mr-2"></i>Create New Invoice</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-add-to-invoice"><i class="fa fa-fw fa-plus mr-2"></i>Add to Existing Invoice</a>
</li>
<?php } ?>
</ul>
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-add-to-invoice"><i class="fa fa-fw fa-plus mr-2"></i>Add to Existing Invoice</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-create-invoice"><i class="fa fa-fw fa-check mr-2"></i>Create New Invoice</a>
</li>
</ul>
<hr>
<hr>
<div class="tab-content">
<?php } ?>
<div class="tab-pane fade show active" id="pills-create-invoice">
<div class="tab-content">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label>Invoice 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"></i></span>
</div>
<input type="date" class="form-control" name="date" max="2999-12-31" value="<?php echo date("Y-m-d"); ?>">
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>Invoice Category <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-list"></i></span>
</div>
<select class="form-control select2" name="category">
<option value="">- Category -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$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 class="input-group-append">
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#addQuickCategoryIncomeModal"><i class="fas fa-fw fa-plus"></i></button>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>Scope</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-comment"></i></span>
</div>
<input type="text" class="form-control" name="scope" placeholder="Quick description" value="Ticket <?php echo "$ticket_prefix$ticket_number - $ticket_subject"; ?>">
</div>
</div>
</div>
<?php
if (mysqli_num_rows($sql_invoices) > 0) { ?>
<div class="tab-pane fade" id="pills-add-to-invoice">
<div class="form-group">
<label>Invoice</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-file-invoice-dollar"></i></span>
</div>
<select class="form-control" name="invoice_id">
<option value="0">- Invoice -</option>
<?php
while ($row = mysqli_fetch_array($sql_invoices)) {
$invoice_id = intval($row['invoice_id']);
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_scope = nullable_htmlentities($row['invoice_scope']);
$invoice_status = nullable_htmlentities($row['invoice_status']);
$invoice_date = nullable_htmlentities($row['invoice_date']);
$invoice_due = nullable_htmlentities($row['invoice_due']);
$invoice_amount = floatval($row['invoice_amount']);
?>
<option value="<?php echo $invoice_id; ?>"><?php echo "$invoice_prefix$invoice_number | $invoice_scope"; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<?php } ?>
</div>
<hr>
<?php
if (mysqli_num_rows($sql_invoices) > 0) { ?>
<div class="tab-pane fade <?php if (mysqli_num_rows($sql_invoices) > 0) { echo "active show"; } ?>" id="pills-add-to-invoice">
<div class="form-group">
<label>Item <strong class="text-danger">*</strong></label>
<label>Existing Invoice</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-box"></i></span>
<span class="input-group-text"><i class="fa fa-fw fa-file-invoice-dollar"></i></span>
</div>
<input type="text" class="form-control" name="item_name" placeholder="Item" value="Support [Hourly]" required>
</div>
</div>
<div class="form-group">
<label>Item Description</label>
<div class="input-group">
<textarea class="form-control" rows="5" name="item_description"><?php echo "# $contact_name - $asset_name - $ticket_date\nTicket $ticket_prefix$ticket_number\n$ticket_subject\nTT: $ticket_total_reply_time"; ?></textarea>
</div>
</div>
<div class="form-row">
<div class="col">
<div class="form-group">
<label>QTY <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-balance-scale"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name="qty" value="<?php echo roundToNearest15($ticket_total_reply_time); ?>" required>
</div>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Price <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-dollar-sign"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name="price" value="<?php echo number_format($client_rate, 2, '.', ''); ?>" required>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>Tax <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-piggy-bank"></i></span>
</div>
<select class="form-control select2" name="tax_id" required>
<option value="0">None</option>
<select class="form-control" name="invoice_id">
<option value="0">- Select an Existing Invoice -</option>
<?php
$taxes_sql = mysqli_query($mysqli, "SELECT * FROM taxes WHERE tax_archived_at IS NULL ORDER BY tax_name ASC");
while ($row = mysqli_fetch_array($taxes_sql)) {
$tax_id_select = intval($row['tax_id']);
$tax_name = nullable_htmlentities($row['tax_name']);
$tax_percent = floatval($row['tax_percent']);
while ($row = mysqli_fetch_array($sql_invoices)) {
$invoice_id = intval($row['invoice_id']);
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_scope = nullable_htmlentities($row['invoice_scope']);
$invoice_status = nullable_htmlentities($row['invoice_status']);
$invoice_date = nullable_htmlentities($row['invoice_date']);
$invoice_due = nullable_htmlentities($row['invoice_due']);
$invoice_amount = floatval($row['invoice_amount']);
?>
<option value="<?php echo $tax_id_select; ?>"><?php echo "$tax_name $tax_percent%"; ?></option>
<option value="<?php echo $invoice_id; ?>"><?php echo "$invoice_prefix$invoice_number | $invoice_scope"; ?></option>
<?php } ?>
</select>
</select>
</div>
</div>
</div>
<?php } ?>
<div class="tab-pane fade <?php if (mysqli_num_rows($sql_invoices) == 0) { echo "active show"; } ?>" id="pills-create-invoice">
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label>Invoice 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"></i></span>
</div>
<input type="date" class="form-control" name="date" max="2999-12-31" value="<?php echo date("Y-m-d"); ?>">
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label>Invoice Category <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-list"></i></span>
</div>
<select class="form-control select2" name="category">
<option value="">- Select a Category -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$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 class="input-group-append">
<button type="button" class="btn btn-secondary ajax-modal" data-modal-url="/admin/modals/category/category_add.php?category=Expense"><i class="fas fa-fw fa-plus"></i></button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_invoice_from_ticket" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Invoice</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
<div class="form-group">
<label>Invoice Title</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-comment"></i></span>
</div>
<select class="form-control select2" name="scope" data-tags="true" data-placeholder="- Enter or Select an Invoice Title -">
<option value=""></option>
<option><?= date('F Y'); ?> Tickets</option>
<option><?= "Ticket $ticket_prefix$ticket_number - $ticket_subject" ?></option>
</select>
</div>
</div>
</form>
</div>
</div>
<div class="form-group">
<label>Item <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-box"></i></span>
</div>
<input type="text" class="form-control" name="item_name" placeholder="Item" value="Support [Hourly]" required>
</div>
</div>
<div class="form-group">
<label>Item Description</label>
<div class="input-group">
<textarea class="form-control" rows="10" name="item_description"><?php
// Build description text cleanly in PHP, not mixed with HTML
$description = "#Ticket: {$ticket_prefix}{$ticket_number} - $ticket_subject\n";
$description .= "Priority: {$ticket_priority}\n";
$description .= "Opened at: {$ticket_date}\n";
if ($ticket_first_response_date_time) {
$description .= "Initial Response: {$ticket_first_response_date_time}\n";
}
if ($ticket_resolved_date) {
$description .= "Resolved at: {$ticket_resolved_date}\n";
}
if ($ticket_assigned_agent) {
$description .= "Agent: {$ticket_assigned_agent}\n";
}
if ($location_id) {
$description .= "Location: {$location_name}\n";
}
if ($contact_id) {
$description .= "Contact: {$contact_name}\n";
}
if ($asset_id) {
$description .= "Asset: {$asset_name}\n";
}
if ($ticket_total_reply_time) {
$description .= "Agent Time Spent: {$ticket_total_reply_time}";
}
echo trim($description); // Trim any leading/trailing spaces/newlines
?></textarea>
</div>
</div>
<div class="form-row">
<div class="col">
<div class="form-group">
<label>QTY <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-balance-scale"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name="qty" value="<?php echo roundToNearest15($ticket_total_reply_time); ?>" required>
</div>
<small class="form-text text-muted">
Based off Ticket time spent <strong><?= $ticket_total_reply_time ?></strong> in 15 Min Increments rounded up.
</small>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Price <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-dollar-sign"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name="price" value="<?php echo number_format($client_rate, 2, '.', ''); ?>" required>
</div>
<small class="form-text text-muted">
Based off Hourly Client rate of <strong><?= numfmt_format_currency($currency_format, $client_rate, $session_company_currency); ?></strong>
</small>
</div>
</div>
</div>
<div class="form-group">
<label>Tax <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-piggy-bank"></i></span>
</div>
<select class="form-control select2" name="tax_id" required>
<option value="0">None</option>
<?php
$taxes_sql = mysqli_query($mysqli, "SELECT * FROM taxes WHERE tax_archived_at IS NULL ORDER BY tax_name ASC");
while ($row = mysqli_fetch_array($taxes_sql)) {
$tax_id_select = intval($row['tax_id']);
$tax_name = nullable_htmlentities($row['tax_name']);
$tax_percent = floatval($row['tax_percent']);
?>
<option value="<?php echo $tax_id_select; ?>"><?php echo "$tax_name $tax_percent%"; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_invoice_from_ticket" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Invoice</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

@@ -0,0 +1,40 @@
<?php
require_once '../../../includes/modal_header.php';
$ticket_id = intval($_GET['ticket_id']);
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title" id="summaryModalTitle">Ticket Summary</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body">
<div id="summaryContent">
<div class="text-center"><i class="fas fa-spinner fa-spin"></i> Generating summary...</div>
</div>
</div>
<script>
$(function() {
$.ajax({
url: 'ajax.php?ai_ticket_summary',
method: 'POST',
data: { ticket_id: <?php echo $ticket_id; ?> },
success: function(response) {
$('#summaryContent').html(response);
},
error: function() {
$('#summaryContent').html('Error generating summary.');
}
});
});
</script>
<?php
require_once '../../../includes/modal_footer.php';

View File

@@ -59,7 +59,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-arrow-right"></i></span>
</div>
<select class="form-control select2" name="destination" data-tags="true" data-placeholder="- Select / Input Destination -" required>
<select class="form-control select2" name="destination" data-tags="true" data-placeholder="- Select or Enter a Destination -" required>
<option value=""></option>
<?php
if ($client_id) {