diff --git a/assets/js/billing.js b/assets/js/billing.js
index 282d32e..4c2f680 100644
--- a/assets/js/billing.js
+++ b/assets/js/billing.js
@@ -1,13 +1,33 @@
function initBillingPage(projectId) {
- document.querySelectorAll('.billing-amount').forEach(input => {
- input.addEventListener('blur', function() {
- const month = this.dataset.month;
- const amount = this.value;
+ const saveBtn = document.getElementById('save-billing');
+ const billingAmountInputs = document.querySelectorAll('.billing-amount');
+ const totalBillingCell = document.getElementById('total-billing');
+
+ 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();
formData.append('projectId', projectId);
- formData.append('month', month);
- formData.append('amount', amount);
+ formData.append('billingData', JSON.stringify(billingData));
fetch('save_billing.php', {
method: 'POST',
@@ -16,9 +36,9 @@ function initBillingPage(projectId) {
.then(response => response.json())
.then(data => {
if (data.success) {
- // Maybe show a small success indicator
+ alert('Billing data saved successfully!');
} else {
- alert('Error saving billing amount: ' + data.error);
+ alert('Error saving billing data: ' + data.error);
}
})
.catch(error => {
@@ -26,5 +46,8 @@ function initBillingPage(projectId) {
alert('An unexpected error occurred.');
});
});
- });
+ }
+
+ // Initial calculation
+ updateTotalBilling();
}
diff --git a/billing.php b/billing.php
index e404f20..9805ab8 100644
--- a/billing.php
+++ b/billing.php
@@ -63,6 +63,7 @@ try {
Billing -
@@ -84,16 +85,20 @@ try {
$currentMonth->modify('+1 month');
}
?>
+ Total |
| Billing |
';
}
?>
+ € |
diff --git a/export_billing.php b/export_billing.php
index 733e481..cb2110c 100644
--- a/export_billing.php
+++ b/export_billing.php
@@ -26,9 +26,12 @@ try {
// Header row
$header = ['Billing'];
+ $totalBilling = 0;
foreach ($billingData as $row) {
$header[] = date("M Y", strtotime($row['month']));
+ $totalBilling += $row['amount'];
}
+ $header[] = 'Total';
fputcsv($output, $header);
// Data row
@@ -36,6 +39,7 @@ try {
foreach ($billingData as $row) {
$data[] = $row['amount'];
}
+ $data[] = $totalBilling;
fputcsv($output, $data);
fclose($output);
diff --git a/save_billing.php b/save_billing.php
index 4481695..961d9b2 100644
--- a/save_billing.php
+++ b/save_billing.php
@@ -6,31 +6,43 @@ $response = ['success' => false, 'error' => 'Invalid request'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$projectId = $_POST['projectId'] ?? null;
- $month = $_POST['month'] ?? null;
- $amount = $_POST['amount'] ?? null;
+ $billingDataJson = $_POST['billingData'] ?? null;
- if ($projectId && $month && $amount !== null) {
- try {
- $pdo = db();
- $stmt = $pdo->prepare("UPDATE billingMonthly SET amount = :amount WHERE projectId = :projectId AND month = :month");
- $stmt->execute([
- ':amount' => $amount,
- ':projectId' => $projectId,
- ':month' => $month
- ]);
+ if ($projectId && $billingDataJson) {
+ $billingData = json_decode($billingDataJson, true);
+
+ if (is_array($billingData)) {
+ try {
+ $pdo = db();
+ $stmt = $pdo->prepare("UPDATE billingMonthly SET amount = :amount WHERE projectId = :projectId AND 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;
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) {
- $response['error'] = 'Database error: ' . $e->getMessage();
+ } else {
+ $response['error'] = 'Invalid billing data format.';
}
} else {
$response['error'] = 'Missing required fields.';
}
}
-echo json_encode($response);
+echo json_encode($response);
\ No newline at end of file
diff --git a/save_override.php b/save_override.php
index 6291136..8503930 100644
--- a/save_override.php
+++ b/save_override.php
@@ -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;
\ No newline at end of file