Files
itflow/agent/modals/client/client_add.php
johnnyq 1e5bffff3c Rates, net terms and SLAs come from the client's contract, else the instance defaults: database 3.5.0 adds a default after-hours rate (Settings > Defaults, now Rates and terms), gives each client whose own rate, net terms or SLAs differ from the defaults an active Standard terms contract setting just those (12-month term renewing itself, starting the day the client was added or the day before its earliest contract, archived with an archived client), deletes per-client SLA assignments and drops clients.client_rate and client_net_terms; time bills at the contract's rate, its after-hours rate or the default after-hours rate, else the default rate, new invoices are due on the contract's net terms else the default, and new tickets get the contract's SLA else the default; a client's own terms still apply until the update runs; the client add and edit windows lose the rate, terms and SLA fields for a note saying what the client is billed on and where it comes from, the Clients list loses Set Hourly Rate and Set Net Terms and shows the contract's rate, the overview's Terms shows the after-hours rate and whether terms are a contract's or the defaults, a contract's page and document show what it leaves empty from another contract in force or the default so signed documents stay unchanged, contract windows show the defaults as placeholders, contract names take a proper possessive; the client import and API create make a Standard terms contract for a rate or terms that aren't the defaults (returning contract_id), API update reports them in not_kept; the client export gives the rates, terms and SLAs as billed; demo data puts each demo client's terms on a contract; changelog updated
2026-10-27 22:22:34 -04:00

325 lines
15 KiB
PHP

<?php
require_once '../../../includes/modal_header.php';
// Filters
$leads_filter = intval($_GET['lead'] ?? 0);
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-user-plus me-2"></i>New <?php if($leads_filter == 0){ echo "Client"; } else { echo "Lead"; } ?></h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<ul class="modal-header nav nav-pills nav-justified">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="pill" href="#pills-details">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="pill" href="#pills-location">Location</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="pill" href="#pills-contact" id="contactNavPill">Contact</a>
</li>
<?php if ($config_module_enable_accounting) { ?>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="pill" href="#pills-billing">Billing</a>
</li>
<?php } ?>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="pill" href="#pills-notes">Notes</a>
</li>
</ul>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
<div class="modal-body">
<div class="tab-content">
<div class="tab-pane fade show active" id="pills-details">
<div class="mb-3">
<label>Name <strong class="text-danger">*</strong> / <span class="text-secondary">Is Lead</span></label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
<input type="text" class="form-control" name="name" id="client_name" placeholder="Name or Company" maxlength="200" onfocusout="checkClientDuplicate()" required autofocus>
<div class="input-group-text">
<input class="form-check-input" type="checkbox" name="lead" value="1" <?php if($leads_filter == 1){ echo "checked"; } ?>>
</div>
</div>
<div class="mt-2">
<span class="text-info" id="client_duplicate_info"></span>
</div>
</div>
<div class="mb-3">
<label>Shortened Name</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-id-badge"></i></span>
<input type="text" class="form-control" name="abbreviation" placeholder="Shortened name for client - Max chars 6" maxlength="6" oninput="this.value = this.value.toUpperCase()">
</div>
</div>
<div class="mb-3">
<label>Industry</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-briefcase"></i></span>
<input type="text" class="form-control" name="type" placeholder="Company Type" maxlength="200">
</div>
</div>
<div class="mb-3">
<label>Referral</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-link"></i></span>
<select class="form-select select2" data-tags="true" name="referral">
<option value="">- Select Referral -</option>
<?= categoryOptionsHtml('Referral') ?>
</select>
<?= categoryAddButtonHtml('Referral', 'btn btn-secondary') ?>
</div>
</div>
<div class="mb-3">
<label>Website</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-globe"></i></span>
<input type="text" class="form-control" name="website" placeholder="ex. google.com" maxlength="200">
</div>
</div>
<div class="mb-3">
<label>Tags</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-tags"></i></span>
<select class="form-select select2" name="tags[]" data-placeholder="Add some tags" multiple<?= !empty($session_is_admin) ? ' data-tags="true"' : '' ?>>
<?= tagOptionsHtml('client', []) ?>
</select>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-location">
<div class="mb-3">
<label>Address</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-map-marker-alt"></i></span>
<input type="text" class="form-control" name="address" placeholder="Street Address" maxlength="200">
</div>
</div>
<div class="mb-3">
<label>City</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-city"></i></span>
<input type="text" class="form-control" name="city" placeholder="City" maxlength="200">
</div>
</div>
<div class="mb-3">
<label>State / Province</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-flag"></i></span>
<input type="text" class="form-control" name="state" placeholder="State or Province" maxlength="200">
</div>
</div>
<div class="mb-3">
<label>Postal Code</label>
<div class="input-group">
<span class="input-group-text"><i class="fab fa-fw fa-usps"></i></span>
<input type="text" class="form-control" name="zip" placeholder="Zip or Postal Code" maxlength="200">
</div>
</div>
<div class="mb-3">
<label>Country</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-globe-americas"></i></span>
<select class="form-select select2" name="country">
<option value="">- Select Country -</option>
<?php foreach($countries_array as $country_name) { ?>
<option <?php if ($session_company_country == $country_name) { echo "selected"; } ?> data-iso2="<?= $country_iso2_array[$country_name] ?? '' ?>"><?= $country_name ?></option>
<?php } ?>
</select>
</div>
</div>
<label>Location Phone / <span class="text-secondary">Extension</span></label>
<div class="row g-2">
<div class="col-9">
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
<input type="hidden" name="location_phone_country_code">
<input type="tel" class="form-control" name="location_phone" placeholder="Phone Number" maxlength="200" data-itflow-phone="location_phone_country_code" data-itflow-phone-country-select="country">
</div>
</div>
</div>
<div class="col-3">
<div class="mb-3">
<input type="text" class="form-control" name="location_extension" placeholder="ext." maxlength="200">
</div>
</div>
</div>
<label>Location Fax</label>
<div class="row g-2">
<div class="col-9">
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
<input type="hidden" name="location_fax_country_code">
<input type="tel" class="form-control" name="location_fax" placeholder="Fax Number" maxlength="200" data-itflow-phone="location_fax_country_code" data-itflow-phone-country-select="country">
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-contact">
<div class="mb-3">
<label>Primary Contact <strong class="text-danger">*</strong></label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-user-check"></i></span>
<input type="text" class="form-control" id="primaryContact" name="contact" placeholder="Primary Contact Person" maxlength="200" required autofocus>
</div>
</div>
<div class="mb-3">
<label>Title</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-id-badge"></i></span>
<input type="text" class="form-control" name="title" placeholder="Title" maxlength="200">
</div>
</div>
<label>Contact Phone / <span class="text-secondary">Extension</span></label>
<div class="row g-2">
<div class="col-9">
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
<input type="hidden" name="contact_phone_country_code">
<input type="tel" class="form-control" name="contact_phone" placeholder="Phone Number" maxlength="200" data-itflow-phone="contact_phone_country_code">
</div>
</div>
</div>
<div class="col-3">
<div class="mb-3">
<input type="text" class="form-control" name="contact_extension" placeholder="ext." maxlength="200">
</div>
</div>
</div>
<label>Mobile</label>
<div class="row g-2">
<div class="col-9">
<div class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
<input type="hidden" name="contact_mobile_country_code">
<input type="tel" class="form-control" name="contact_mobile" placeholder="Mobile Phone Number" maxlength="200" data-itflow-phone="contact_mobile_country_code">
</div>
</div>
</div>
</div>
<div class="mb-3">
<label>Contact Email</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
<input type="email" class="form-control" name="contact_email" placeholder="Contact's Email Address" maxlength="200">
</div>
</div>
</div>
<?php if ($config_module_enable_accounting) { ?>
<div class="tab-pane fade" id="pills-billing">
<?php $terms_note_client_id = 0; require __DIR__ . '/client_terms_note.php'; ?>
<div class="mb-3">
<label>Tax ID</label>
<div class="input-group">
<span class="input-group-text"><i class="fa fa-fw fa-balance-scale"></i></span>
<input type="text" class="form-control" name="tax_id_number" placeholder="Tax ID Number" maxlength="255">
</div>
</div>
<?php
$client_tax = [];
$client_tax_key = 'New';
require __DIR__ . '/client_tax_fields.php';
?>
<div class="mb-3">
<input type="hidden" name="reminders_field" value="1">
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" name="reminders" value="1" id="clientRemindersNew" checked>
<label class="form-check-label" for="clientRemindersNew">Payment reminders and statements</label>
</div>
<small class="text-secondary">Emailed as set in Invoice Settings. Off, this client gets neither - invoices can still be sent by hand.</small>
</div>
</div>
<?php } ?>
<div class="tab-pane fade" id="pills-notes">
<div class="mb-3">
<textarea class="form-control" rows="10" name="notes" placeholder="Enter some notes"></textarea>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_client" class="btn btn-primary text-bold" onclick="promptPrimaryContact()"><i class="fa fa-check me-2"></i>Create Client</button>
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal"><i class="fa fa-times me-2"></i>Close</button>
</div>
</form>
<script>
// Checks/prompts that the primary contact field (required) is populated
function promptPrimaryContact() {
let primaryContactField = document.getElementById("primaryContact").value;
if (primaryContactField == null || primaryContactField === "") {
document.getElementById("contactNavPill").click();
}
}
</script>
<script>
// Checks for duplicate clients
function checkClientDuplicate() {
var name = document.getElementById("client_name").value;
//Send a GET request to ajax.php as ajax.php?client_duplicate_check=true&name=NAME
itflowGet(
"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';