Auto commit: 2025-11-27T12:16:59.506Z
This commit is contained in:
parent
893b3b9bfa
commit
ffe0142f5f
@ -1,13 +1,33 @@
|
|||||||
function initBillingPage(projectId) {
|
function initBillingPage(projectId) {
|
||||||
document.querySelectorAll('.billing-amount').forEach(input => {
|
const saveBtn = document.getElementById('save-billing');
|
||||||
input.addEventListener('blur', function() {
|
const billingAmountInputs = document.querySelectorAll('.billing-amount');
|
||||||
const month = this.dataset.month;
|
const totalBillingCell = document.getElementById('total-billing');
|
||||||
const amount = this.value;
|
|
||||||
|
function updateTotalBilling() {
|
||||||
|
let total = 0;
|
||||||
|
billingAmountInputs.forEach(input => {
|
||||||
|
total += parseFloat(input.value) || 0;
|
||||||
|
});
|
||||||
|
totalBillingCell.textContent = `€${total.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
billingAmountInputs.forEach(input => {
|
||||||
|
input.addEventListener('keyup', updateTotalBilling);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (saveBtn) {
|
||||||
|
saveBtn.addEventListener('click', function() {
|
||||||
|
const billingData = [];
|
||||||
|
billingAmountInputs.forEach(input => {
|
||||||
|
billingData.push({
|
||||||
|
month: input.dataset.month,
|
||||||
|
amount: input.value
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('projectId', projectId);
|
formData.append('projectId', projectId);
|
||||||
formData.append('month', month);
|
formData.append('billingData', JSON.stringify(billingData));
|
||||||
formData.append('amount', amount);
|
|
||||||
|
|
||||||
fetch('save_billing.php', {
|
fetch('save_billing.php', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -16,9 +36,9 @@ function initBillingPage(projectId) {
|
|||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
// Maybe show a small success indicator
|
alert('Billing data saved successfully!');
|
||||||
} else {
|
} else {
|
||||||
alert('Error saving billing amount: ' + data.error);
|
alert('Error saving billing data: ' + data.error);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@ -26,5 +46,8 @@ function initBillingPage(projectId) {
|
|||||||
alert('An unexpected error occurred.');
|
alert('An unexpected error occurred.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// Initial calculation
|
||||||
|
updateTotalBilling();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,6 +63,7 @@ try {
|
|||||||
<h1 class="h2">Billing - <?php echo htmlspecialchars($project['name']); ?></h1>
|
<h1 class="h2">Billing - <?php echo htmlspecialchars($project['name']); ?></h1>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<a href="project_details.php?id=<?php echo $projectId; ?>" class="btn btn-secondary">Return</a>
|
<a href="project_details.php?id=<?php echo $projectId; ?>" class="btn btn-secondary">Return</a>
|
||||||
|
<button id="save-billing" class="btn btn-primary">Save</button>
|
||||||
<a href="export_billing.php?id=<?php echo $projectId; ?>" class="btn btn-secondary">Export to Excel</a>
|
<a href="export_billing.php?id=<?php echo $projectId; ?>" class="btn btn-secondary">Export to Excel</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -84,16 +85,20 @@ try {
|
|||||||
$currentMonth->modify('+1 month');
|
$currentMonth->modify('+1 month');
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
<th style="width: 150px;">Total</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Billing</td>
|
<td>Billing</td>
|
||||||
<?php
|
<?php
|
||||||
|
$totalBilling = 0;
|
||||||
foreach ($billingData as $billingMonth) {
|
foreach ($billingData as $billingMonth) {
|
||||||
|
$totalBilling += $billingMonth['amount'];
|
||||||
echo '<td><input type="number" class="form-control billing-amount" data-month="' . $billingMonth['month'] . '" value="' . htmlspecialchars($billingMonth['amount']) . '"></td>';
|
echo '<td><input type="number" class="form-control billing-amount" data-month="' . $billingMonth['month'] . '" value="' . htmlspecialchars($billingMonth['amount']) . '"></td>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
<td id="total-billing" class="fw-bold">€<?php echo number_format($totalBilling, 2); ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@ -26,9 +26,12 @@ try {
|
|||||||
|
|
||||||
// Header row
|
// Header row
|
||||||
$header = ['Billing'];
|
$header = ['Billing'];
|
||||||
|
$totalBilling = 0;
|
||||||
foreach ($billingData as $row) {
|
foreach ($billingData as $row) {
|
||||||
$header[] = date("M Y", strtotime($row['month']));
|
$header[] = date("M Y", strtotime($row['month']));
|
||||||
|
$totalBilling += $row['amount'];
|
||||||
}
|
}
|
||||||
|
$header[] = 'Total';
|
||||||
fputcsv($output, $header);
|
fputcsv($output, $header);
|
||||||
|
|
||||||
// Data row
|
// Data row
|
||||||
@ -36,6 +39,7 @@ try {
|
|||||||
foreach ($billingData as $row) {
|
foreach ($billingData as $row) {
|
||||||
$data[] = $row['amount'];
|
$data[] = $row['amount'];
|
||||||
}
|
}
|
||||||
|
$data[] = $totalBilling;
|
||||||
fputcsv($output, $data);
|
fputcsv($output, $data);
|
||||||
|
|
||||||
fclose($output);
|
fclose($output);
|
||||||
|
|||||||
@ -6,31 +6,43 @@ $response = ['success' => false, 'error' => 'Invalid request'];
|
|||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$projectId = $_POST['projectId'] ?? null;
|
$projectId = $_POST['projectId'] ?? null;
|
||||||
$month = $_POST['month'] ?? null;
|
$billingDataJson = $_POST['billingData'] ?? null;
|
||||||
$amount = $_POST['amount'] ?? null;
|
|
||||||
|
|
||||||
if ($projectId && $month && $amount !== null) {
|
if ($projectId && $billingDataJson) {
|
||||||
try {
|
$billingData = json_decode($billingDataJson, true);
|
||||||
$pdo = db();
|
|
||||||
$stmt = $pdo->prepare("UPDATE billingMonthly SET amount = :amount WHERE projectId = :projectId AND month = :month");
|
if (is_array($billingData)) {
|
||||||
$stmt->execute([
|
try {
|
||||||
':amount' => $amount,
|
$pdo = db();
|
||||||
':projectId' => $projectId,
|
$stmt = $pdo->prepare("UPDATE billingMonthly SET amount = :amount WHERE projectId = :projectId AND month = :month");
|
||||||
':month' => $month
|
|
||||||
]);
|
$pdo->beginTransaction();
|
||||||
|
foreach ($billingData as $item) {
|
||||||
|
$stmt->execute([
|
||||||
|
':amount' => $item['amount'],
|
||||||
|
':projectId' => $projectId,
|
||||||
|
':month' => $item['month']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
if ($stmt->rowCount() > 0) {
|
|
||||||
$response['success'] = true;
|
$response['success'] = true;
|
||||||
unset($response['error']);
|
unset($response['error']);
|
||||||
} else {
|
|
||||||
$response['error'] = 'No record found to update.';
|
} catch (PDOException $e) {
|
||||||
|
if ($pdo->inTransaction()) {
|
||||||
|
$pdo->rollBack();
|
||||||
|
}
|
||||||
|
$response['error'] = 'Database error: ' . $e->getMessage();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$response['error'] = 'An unexpected error occurred: ' . $e->getMessage();
|
||||||
}
|
}
|
||||||
} catch (PDOException $e) {
|
} else {
|
||||||
$response['error'] = 'Database error: ' . $e->getMessage();
|
$response['error'] = 'Invalid billing data format.';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$response['error'] = 'Missing required fields.';
|
$response['error'] = 'Missing required fields.';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode($response);
|
echo json_encode($response);
|
||||||
@ -93,5 +93,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode($response);
|
try {
|
||||||
|
echo json_encode($response, JSON_THROW_ON_ERROR);
|
||||||
|
} catch (JsonException $e) {
|
||||||
|
error_log('JSON encoding error: ' . $e->getMessage());
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Internal server error during JSON encoding.']);
|
||||||
|
}
|
||||||
exit;
|
exit;
|
||||||
Loading…
x
Reference in New Issue
Block a user