overrride - works
This commit is contained in:
parent
47807955ad
commit
2b9925f4fc
76
assets/js/project_details.js
Normal file
76
assets/js/project_details.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
const overrideBtn = document.getElementById('override-btn');
|
||||||
|
|
||||||
|
if (overrideBtn) {
|
||||||
|
overrideBtn.addEventListener('click', function () {
|
||||||
|
const projectId = this.dataset.projectId;
|
||||||
|
const month = this.dataset.month;
|
||||||
|
|
||||||
|
if (this.textContent.trim() === 'Override') {
|
||||||
|
this.textContent = 'Save';
|
||||||
|
this.classList.remove('btn-warning');
|
||||||
|
this.classList.add('btn-success');
|
||||||
|
|
||||||
|
makeEditable('WIP', month);
|
||||||
|
makeEditable('Opening-Balance', month);
|
||||||
|
makeEditable('Billings', month);
|
||||||
|
makeEditable('Expenses', month);
|
||||||
|
|
||||||
|
} else if (this.textContent.trim() === 'Save') {
|
||||||
|
const wip = document.getElementById(`wip-${month}-input`).value;
|
||||||
|
const openingBalance = document.getElementById(`opening-balance-${month}-input`).value;
|
||||||
|
const billings = document.getElementById(`billings-${month}-input`).value;
|
||||||
|
const expenses = document.getElementById(`expenses-${month}-input`).value;
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('projectId', projectId);
|
||||||
|
formData.append('month', month);
|
||||||
|
formData.append('wip', wip);
|
||||||
|
formData.append('openingBalance', openingBalance);
|
||||||
|
formData.append('billings', billings);
|
||||||
|
formData.append('expenses', expenses);
|
||||||
|
|
||||||
|
fetch('save_override.php', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
this.textContent = 'Overridden';
|
||||||
|
this.classList.remove('btn-success');
|
||||||
|
this.classList.add('btn-secondary');
|
||||||
|
this.disabled = true;
|
||||||
|
|
||||||
|
updateCell('WIP', month, wip);
|
||||||
|
updateCell('Opening-Balance', month, openingBalance);
|
||||||
|
updateCell('Billings', month, billings);
|
||||||
|
updateCell('Expenses', month, expenses);
|
||||||
|
} else {
|
||||||
|
alert('Error saving override: ' + data.error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
alert('An unexpected error occurred.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeEditable(metric, month) {
|
||||||
|
const cell = document.getElementById(`${metric.toLowerCase().replace(/\s/g, '-')}-${month}`);
|
||||||
|
if (cell) {
|
||||||
|
const value = cell.textContent.replace(/€/g, '').replace(/,/g, '');
|
||||||
|
cell.innerHTML = `<input type="number" id="${metric.toLowerCase().replace(/\s/g, '-')}-${month}-input" class="form-control" value="${value}">`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCell(metric, month, value) {
|
||||||
|
const cell = document.getElementById(`${metric.toLowerCase().replace(/\s/g, '-')}-${month}`);
|
||||||
|
if (cell) {
|
||||||
|
cell.innerHTML = `€${parseFloat(value).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -3,7 +3,6 @@ CREATE TABLE IF NOT EXISTS `projectFinanceMonthly` (
|
|||||||
`projectId` INT NOT NULL,
|
`projectId` INT NOT NULL,
|
||||||
`metricName` VARCHAR(255) NOT NULL,
|
`metricName` VARCHAR(255) NOT NULL,
|
||||||
`month` DATE NOT NULL,
|
`month` DATE NOT NULL,
|
||||||
`amount` DECIMAL(15, 2) NOT NULL,
|
|
||||||
`createdAt` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
`createdAt` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
`updatedAt` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`updatedAt` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (`projectId`) REFERENCES `projects`(`id`) ON DELETE CASCADE,
|
FOREIGN KEY (`projectId`) REFERENCES `projects`(`id`) ON DELETE CASCADE,
|
||||||
|
|||||||
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
ALTER TABLE `projectFinanceMonthly`
|
||||||
|
ADD COLUMN `value` DECIMAL(15, 2) NOT NULL DEFAULT 0.00,
|
||||||
|
ADD COLUMN `is_overridden` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
3
db/migrations/010_fix_project_finance_monthly_table.sql
Normal file
3
db/migrations/010_fix_project_finance_monthly_table.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `projectFinanceMonthly` ADD COLUMN `metricName` VARCHAR(255) NOT NULL AFTER `projectId`;
|
||||||
|
ALTER TABLE `projectFinanceMonthly` ADD COLUMN `value` DECIMAL(15, 2) NOT NULL DEFAULT 0.00;
|
||||||
|
ALTER TABLE `projectFinanceMonthly` ADD COLUMN `is_overridden` BOOLEAN NOT NULL DEFAULT FALSE;
|
||||||
@ -236,17 +236,35 @@ if (!$project) {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr class="text-center">
|
<tr class="text-center">
|
||||||
<th class="bg-body-tertiary" style="min-width: 150px;">Metric</th>
|
<th class="bg-body-tertiary" style="min-width: 150px;">Metric</th>
|
||||||
<?php foreach ($months as $month): ?>
|
<?php
|
||||||
<th><?php echo date('M Y', strtotime($month)); ?></th>
|
$is_first_month = true;
|
||||||
<?php endforeach; ?>
|
foreach ($months as $month): ?>
|
||||||
|
<th>
|
||||||
|
<?php echo date('M Y', strtotime($month)); ?>
|
||||||
|
<?php if ($is_first_month): ?>
|
||||||
|
<button id="override-btn" class="btn btn-warning btn-sm mt-1" data-project-id="<?php echo $project_id; ?>" data-month="<?php echo $month; ?>">Override</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</th>
|
||||||
|
<?php
|
||||||
|
$is_first_month = false;
|
||||||
|
endforeach; ?>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($metrics as $metric): ?>
|
<?php
|
||||||
|
$editable_metrics = ['WIP', 'Opening Balance', 'Billings', 'Expenses'];
|
||||||
|
foreach ($metrics as $metric): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="fw-bold bg-body-tertiary"><?php echo $metric; ?></td>
|
<td class="fw-bold bg-body-tertiary"><?php echo $metric; ?></td>
|
||||||
<?php foreach ($months as $month): ?>
|
<?php
|
||||||
<td class="text-end">
|
$is_first_month_for_body = true;
|
||||||
|
foreach ($months as $month):
|
||||||
|
$cell_id = '';
|
||||||
|
if ($is_first_month_for_body && in_array($metric, $editable_metrics)) {
|
||||||
|
$cell_id = 'id="' . str_replace(' ', '-', strtolower($metric)) . '-' . $month . '"';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<td class="text-end" <?php echo $cell_id; ?>>
|
||||||
<?php
|
<?php
|
||||||
if ($metric === 'Margin') {
|
if ($metric === 'Margin') {
|
||||||
echo number_format(($financial_data[$metric][$month] ?? 0) * 100, 2) . '%';
|
echo number_format(($financial_data[$metric][$month] ?? 0) * 100, 2) . '%';
|
||||||
@ -255,7 +273,9 @@ if (!$project) {
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</td>
|
</td>
|
||||||
<?php endforeach; ?>
|
<?php
|
||||||
|
$is_first_month_for_body = false;
|
||||||
|
endforeach; ?>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -268,5 +288,6 @@ if (!$project) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="assets/js/project_details.js?v=<?php echo time(); ?>"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
49
save_override.php
Normal file
49
save_override.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
$response = ['success' => false, 'error' => 'Invalid request'];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$project_id = $_POST['projectId'] ?? null;
|
||||||
|
$month = $_POST['month'] ?? null;
|
||||||
|
|
||||||
|
$metrics = [
|
||||||
|
'wip' => $_POST['wip'] ?? null,
|
||||||
|
'opening_balance' => $_POST['openingBalance'] ?? null,
|
||||||
|
'billings' => $_POST['billings'] ?? null,
|
||||||
|
'expenses' => $_POST['expenses'] ?? null,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($project_id && $month && !in_array(null, $metrics, true)) {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "INSERT INTO projectFinanceMonthly (projectId, month, metricName, value, is_overridden)
|
||||||
|
VALUES (:pid, :m, :metric, :val, 1)
|
||||||
|
ON DUPLICATE KEY UPDATE value = :val, is_overridden = 1";
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare($sql);
|
||||||
|
|
||||||
|
foreach ($metrics as $metricName => $value) {
|
||||||
|
$processedValue = ($value === '' || $value === null) ? 0.00 : $value;
|
||||||
|
$stmt->execute([
|
||||||
|
':pid' => $project_id,
|
||||||
|
':m' => $month,
|
||||||
|
':metric' => $metricName,
|
||||||
|
':val' => $processedValue
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = ['success' => true];
|
||||||
|
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$response['error'] = 'Database error: ' . $e->getMessage();
|
||||||
|
error_log($e->getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response['error'] = 'Missing required fields.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($response);
|
||||||
Loading…
x
Reference in New Issue
Block a user