mirror of
https://github.com/itflow-org/itflow
synced 2026-11-11 23:17:23 +00:00
127 lines
8.1 KiB
PHP
127 lines
8.1 KiB
PHP
<?php
|
|
|
|
/*
|
|
* ITFlow - Database update to version 3.5.0 (from 3.4.9)
|
|
* Included by admin/database_updates.php - do not access directly
|
|
*
|
|
* A client has no hourly rate, net terms or SLAs of its own any more: they
|
|
* come from its contract in force, else the defaults (Admin > Settings >
|
|
* Defaults, Admin > SLAs) - functions/contract_billing.php.
|
|
*
|
|
* settings.config_default_after_hours_rate the default after-hours rate -
|
|
* NULL, none: the hourly rate
|
|
* applies after hours too
|
|
* clients.client_rate, client_net_terms dropped
|
|
* sla_assignments (client_id > 0) deleted - client 0's rows are
|
|
* the defaults and stay
|
|
*
|
|
* A client whose own rate, net terms or SLAs differ from the defaults keeps
|
|
* them, on a contract named "Standard terms" made for it here: active,
|
|
* 12-month term renewing itself, no notice, setting only what differs. It
|
|
* starts the day the client was added - before any contract the client
|
|
* already has, so that one's terms still come first where it sets them, as
|
|
* they did over the client's own. Its term is carried on to the one running
|
|
* today. An archived client's is archived with it. A client SLA pointing at
|
|
* no SLA, or at an archived one (the client's tickets got none), can't be
|
|
* kept: a contract sets an SLA or leaves the default.
|
|
*/
|
|
|
|
defined('FROM_DB_UPDATER') || die("Direct file access is not allowed");
|
|
|
|
$itflow_column = function ($table, $column) use ($mysqli) {
|
|
$result = mysqli_query($mysqli, "SELECT 1 FROM information_schema.COLUMNS
|
|
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = '$table' AND COLUMN_NAME = '$column' LIMIT 1");
|
|
return $result && mysqli_num_rows($result) > 0;
|
|
};
|
|
|
|
if (!$itflow_column('settings', 'config_default_after_hours_rate')) {
|
|
mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_default_after_hours_rate` decimal(15,2) DEFAULT NULL AFTER `config_default_hourly_rate`");
|
|
}
|
|
|
|
if ($itflow_column('clients', 'client_rate') && $itflow_column('clients', 'client_net_terms')) {
|
|
|
|
$itflow_settings = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT config_default_hourly_rate, config_default_net_terms FROM settings WHERE company_id = 1")) ?: [];
|
|
$itflow_default_rate = round(floatval($itflow_settings['config_default_hourly_rate'] ?? 0), 2);
|
|
$itflow_default_net = intval($itflow_settings['config_default_net_terms'] ?? 0);
|
|
|
|
// The default SLA for each priority - one that is archived counts as none, as it did for tickets
|
|
$itflow_parts = ['Low' => 'low', 'Medium' => 'medium', 'High' => 'high', 'Urgent' => 'urgent'];
|
|
$itflow_live_slas = [];
|
|
$itflow_sql = mysqli_query($mysqli, "SELECT sla_id FROM slas WHERE sla_archived_at IS NULL");
|
|
while ($itflow_sql && ($itflow_row = mysqli_fetch_row($itflow_sql))) {
|
|
$itflow_live_slas[intval($itflow_row[0])] = true;
|
|
}
|
|
$itflow_default_slas = array_fill_keys(array_keys($itflow_parts), 0);
|
|
$itflow_client_slas = [];
|
|
$itflow_sql = mysqli_query($mysqli, "SELECT sla_assignment_client_id, sla_assignment_priority, sla_assignment_sla_id FROM sla_assignments");
|
|
while ($itflow_sql && ($itflow_row = mysqli_fetch_assoc($itflow_sql))) {
|
|
$itflow_priority = (string) $itflow_row['sla_assignment_priority'];
|
|
$itflow_sla_id = intval($itflow_row['sla_assignment_sla_id']);
|
|
if (!isset($itflow_parts[$itflow_priority]) || !isset($itflow_live_slas[$itflow_sla_id])) {
|
|
continue;
|
|
}
|
|
if (intval($itflow_row['sla_assignment_client_id']) === 0) {
|
|
$itflow_default_slas[$itflow_priority] = $itflow_sla_id;
|
|
} else {
|
|
$itflow_client_slas[intval($itflow_row['sla_assignment_client_id'])][$itflow_priority] = $itflow_sla_id;
|
|
}
|
|
}
|
|
|
|
$itflow_today = date('Y-m-d');
|
|
// A client given its Standard terms by an earlier run that stopped part way is left as it is
|
|
$itflow_sql = mysqli_query($mysqli, "SELECT client_id, client_rate, client_net_terms, client_created_at, client_archived_at,
|
|
(SELECT MIN(contract_start_date) FROM contracts WHERE contract_client_id = client_id AND contract_start_date IS NOT NULL) AS first_contract_start
|
|
FROM clients
|
|
WHERE NOT EXISTS (SELECT 1 FROM contracts WHERE contract_client_id = client_id AND contract_name = 'Standard terms' AND contract_notes LIKE 'Made by the 26.11 update%')
|
|
ORDER BY client_id");
|
|
while ($itflow_sql && ($itflow_client = mysqli_fetch_assoc($itflow_sql))) {
|
|
$itflow_client_id = intval($itflow_client['client_id']);
|
|
$itflow_set = [];
|
|
|
|
// Only what differs from the defaults - a rate of nothing was no rate, the default applied. A
|
|
// contract's rate holds under 100,000,000.00 - a rate past that was typed in by mistake, and
|
|
// is left out (the default applies), or the contract couldn't be made and the update would stop
|
|
$itflow_rate = round(floatval($itflow_client['client_rate']), 2);
|
|
if ($itflow_rate > 0 && $itflow_rate < 100000000 && $itflow_rate != $itflow_default_rate) {
|
|
$itflow_set[] = "contract_rate_standard = " . sprintf('%.2f', $itflow_rate);
|
|
}
|
|
if ($itflow_client['client_net_terms'] !== null && intval($itflow_client['client_net_terms']) !== $itflow_default_net) {
|
|
$itflow_set[] = "contract_net_terms = " . intval($itflow_client['client_net_terms']);
|
|
}
|
|
foreach ($itflow_parts as $itflow_priority => $itflow_part) {
|
|
$itflow_sla_id = intval($itflow_client_slas[$itflow_client_id][$itflow_priority] ?? 0);
|
|
if ($itflow_sla_id && $itflow_sla_id !== $itflow_default_slas[$itflow_priority]) {
|
|
$itflow_set[] = "contract_sla_{$itflow_part}_id = $itflow_sla_id";
|
|
}
|
|
}
|
|
if (!$itflow_set) {
|
|
continue;
|
|
}
|
|
|
|
// From the day the client was added, before any contract it already has
|
|
$itflow_start = substr((string) $itflow_client['client_created_at'], 0, 10);
|
|
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $itflow_start) || $itflow_start === '0000-00-00') {
|
|
$itflow_start = $itflow_today;
|
|
}
|
|
$itflow_first = (string) $itflow_client['first_contract_start'];
|
|
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $itflow_first) && $itflow_first !== '0000-00-00' && $itflow_first <= $itflow_start) {
|
|
$itflow_start = date('Y-m-d', strtotime('-1 day', strtotime($itflow_first)));
|
|
}
|
|
// Its 12-month term carried on to the one running today
|
|
$itflow_end = date('Y-m-d', strtotime('+12 months -1 day', strtotime($itflow_start)));
|
|
while ($itflow_end < $itflow_today) {
|
|
$itflow_end = date('Y-m-d', strtotime('+12 months -1 day', strtotime('+1 day', strtotime($itflow_end))));
|
|
}
|
|
|
|
$itflow_archived = $itflow_client['client_archived_at'] ? "'" . mysqli_real_escape_string($mysqli, $itflow_client['client_archived_at']) . "'" : 'NULL';
|
|
mysqli_query($mysqli, "INSERT INTO contracts SET contract_name = 'Standard terms', contract_status = 'Active', contract_type = 'other',
|
|
contract_client_id = $itflow_client_id, contract_start_date = '$itflow_start', contract_end_date = '$itflow_end',
|
|
contract_term_months = 12, contract_auto_renew = 1, contract_notice_days = 0, contract_archived_at = $itflow_archived,
|
|
contract_notes = 'Made by the 26.11 update from the hourly rate, net terms and SLAs the client had of its own, where they differed from the defaults - a client has none of its own from 26.11.',
|
|
" . implode(', ', $itflow_set));
|
|
}
|
|
|
|
mysqli_query($mysqli, "DELETE FROM sla_assignments WHERE sla_assignment_client_id > 0");
|
|
mysqli_query($mysqli, "ALTER TABLE `clients` DROP `client_rate`, DROP `client_net_terms`");
|
|
}
|