408 lines
21 KiB
PHP
408 lines
21 KiB
PHP
<?php
|
|
require('../.hta_config/conf.php');
|
|
$db = new PDO("mysql:host=$mariaServer;dbname=$mariaDb", $mariaUser, $mariaPass);
|
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
$customerId = $_GET['customerId'];
|
|
$invoiceId = $_GET['invoiceId'];
|
|
|
|
if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['additional-payment'])){
|
|
$adPaymentAmount = floatval($_POST['adPaymentAmount']);
|
|
$adPaymentDate = $_POST['adPaymentDate'];
|
|
$adPaymentSource = $_POST['adPaymentSource'];
|
|
$adPaymentTran = $_POST['adPaymentTran'];
|
|
$adPaymentRemarks = $_POST['adPaymentRemarks'];
|
|
|
|
// Insert additional payment record
|
|
try {
|
|
$stmt3 = $db->prepare("INSERT INTO emi (customerId, invoiceId, adPaymentAmount, adPaymentDate, adPaymentSource, adPaymentTran, adPaymentRemarks, payStatus) VALUES (:customerId, :invoiceId, :adPaymentAmount, :adPaymentDate, :adPaymentSource, :adPaymentTran, :adPaymentRemarks, 1)");
|
|
$stmt3->bindParam(':customerId', $customerId);
|
|
$stmt3->bindParam(':invoiceId', $invoiceId);
|
|
$stmt3->bindParam(':adPaymentAmount', $adPaymentAmount);
|
|
$stmt3->bindParam(':adPaymentDate', $adPaymentDate);
|
|
$stmt3->bindParam(':adPaymentSource', $adPaymentSource);
|
|
$stmt3->bindParam(':adPaymentTran', $adPaymentTran);
|
|
$stmt3->bindParam(':adPaymentRemarks', $adPaymentRemarks);
|
|
$stmt3->execute();
|
|
echo '<div class="alert alert-success">Additional Payment <strong>' . htmlspecialchars($_POST['adPaymentAmount']) . '</strong> applied successfully.</div>';
|
|
} catch(PDOException $e) {
|
|
echo '<div class="alert alert-danger">Error: ' . $e->getMessage() . '</div>';
|
|
}
|
|
|
|
// Apply additional payment to EMIs (starting from furthest future EMI)
|
|
try {
|
|
// Get all unpaid EMIs ordered by date DESC (furthest future first)
|
|
$stmt = $db->prepare("SELECT * FROM emi WHERE customerId = :customerId AND invoiceId = :invoiceId AND emiAmount > 0 AND payStatus = 0 ORDER BY emiDate DESC");
|
|
$stmt->bindParam(':customerId', $customerId);
|
|
$stmt->bindParam(':invoiceId', $invoiceId);
|
|
$stmt->execute();
|
|
$emiRecords = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$remainingAmount = $adPaymentAmount;
|
|
|
|
foreach ($emiRecords as $emi) {
|
|
if ($remainingAmount <= 0) break;
|
|
|
|
$emiId = $emi['id'];
|
|
$emiAmount = floatval($emi['emiAmount']);
|
|
|
|
if ($remainingAmount >= $emiAmount) {
|
|
// Full payment
|
|
$remainingAmount -= $emiAmount;
|
|
$newEmiAmount = 0;
|
|
$payStatus = 1;
|
|
} else {
|
|
// Partial payment
|
|
$newEmiAmount = $emiAmount - $remainingAmount;
|
|
$remainingAmount = 0;
|
|
$payStatus = 0; // Still partially unpaid
|
|
}
|
|
|
|
// Update EMI
|
|
$updateStmt = $db->prepare("UPDATE emi SET emiAmount = :newEmiAmount, payStatus = :payStatus, paymentDate = CASE WHEN :payStatus = 1 THEN :paymentDate ELSE paymentDate END WHERE id = :emiId");
|
|
$updateStmt->bindParam(':newEmiAmount', $newEmiAmount);
|
|
$updateStmt->bindParam(':payStatus', $payStatus);
|
|
$updateStmt->bindParam(':paymentDate', $adPaymentDate);
|
|
$updateStmt->bindParam(':emiId', $emiId);
|
|
$updateStmt->execute();
|
|
}
|
|
|
|
// If there's remaining amount after processing all unpaid EMIs
|
|
if ($remainingAmount > 0) {
|
|
echo '<div class="alert alert-info">Note: $' . number_format($remainingAmount, 2) . ' was not applied (no unpaid EMIs remaining)</div>';
|
|
}
|
|
|
|
} catch (PDOException $e) {
|
|
echo '<div class="alert alert-danger">Error: ' . $e->getMessage() . '</div>';
|
|
}
|
|
}
|
|
// if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['additional-payment'])){
|
|
// $adPaymentAmount = floatval($_POST['adPaymentAmount']);
|
|
// $adPaymentDate = $_POST['adPaymentDate'];
|
|
// $adPaymentSource = $_POST['adPaymentSource'];
|
|
// $adPaymentTran = $_POST['adPaymentTran'];
|
|
// $adPaymentRemarks = $_POST['adPaymentRemarks'];
|
|
// // Insert additional payment record
|
|
// try{
|
|
// $stmt3 = $db->prepare("INSERT INTO emi (customerId, invoiceId, adPaymentAmount, adPaymentDate, adPaymentSource, adPaymentTran, adPaymentRemarks, payStatus) VALUES (:customerId, :invoiceId, :adPaymentAmount, :adPaymentDate, :adPaymentSource, :adPaymentTran, :adPaymentRemarks, 1)");
|
|
// $stmt3->bindParam(':customerId', $customerId);
|
|
// $stmt3->bindParam(':invoiceId', $invoiceId);
|
|
// $stmt3->bindParam(':adPaymentAmount', $adPaymentAmount);
|
|
// $stmt3->bindParam(':adPaymentDate', $adPaymentDate);
|
|
// $stmt3->bindParam(':adPaymentSource', $adPaymentSource);
|
|
// $stmt3->bindParam(':adPaymentTran', $adPaymentTran);
|
|
// $stmt3->bindParam(':adPaymentRemarks', $adPaymentRemarks);
|
|
// if ($stmt3->execute()) {
|
|
// echo '<div class="alert alert-success">Additional Payment <strong>' . htmlspecialchars($_POST['adPaymentAmount']) . '</strong> applied successfully.</div>';
|
|
// } else {
|
|
// echo '<div class="alert alert-danger">Failed to record the additional payment.</div>';
|
|
// }
|
|
// }catch(PDOException $e){
|
|
// echo '<div class="alert alert-danger">Error: ' . $e->getMessage() . '</div>';
|
|
// }
|
|
// }
|
|
|
|
// if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
// $adPaymentAmount = floatval($_POST['adPaymentAmount']);
|
|
// try {
|
|
// // Fetch EMIs of the customer (Assuming we have emiNumber in ascending order)
|
|
// $stmt = $db->prepare("SELECT * FROM emi WHERE customerId = :customerId AND invoiceId = :invoiceId ORDER BY emiNumber DESC");
|
|
// $stmt->bindParam(':customerId', $customerId);
|
|
// $stmt->bindParam(':invoiceId', $invoiceId);
|
|
// $stmt->execute();
|
|
// $emiRecords = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// if (!$emiRecords) {
|
|
// echo '<div class="alert alert-danger">No EMI records found.</div>';
|
|
// exit;
|
|
// }
|
|
|
|
// $remainingAmount = $adPaymentAmount;
|
|
// foreach ($emiRecords as $index => &$emi) {
|
|
// if ($remainingAmount <= 0) break;
|
|
|
|
// $emiId = $emi['id'];
|
|
// $emiAmount = floatval($emi['emiAmount']);
|
|
|
|
// if ($remainingAmount >= $emiAmount) {
|
|
// // If additional amount is greater or equal to EMI, pay it off
|
|
// $payAmount = $emiAmount;
|
|
// $remainingAmount -= $emiAmount;
|
|
// $newEmiAmount = 0; // EMI is fully paid
|
|
// } else {
|
|
// // If additional amount is less than EMI, reduce this EMI
|
|
// $payAmount = $remainingAmount;
|
|
// $newEmiAmount = $emiAmount - $remainingAmount;
|
|
// $remainingAmount = 0; // No more amount left to deduct
|
|
// }
|
|
|
|
// // Update EMI record with reduced amount
|
|
// $updateStmt = $db->prepare("UPDATE emi SET emiAmount = :newEmiAmount, payStatus = CASE WHEN emiAmount = 0 THEN 1 ELSE 0 END WHERE id = :emiId");
|
|
// $updateStmt->bindParam(':newEmiAmount', $newEmiAmount);
|
|
// $updateStmt->bindParam(':emiId', $emiId);
|
|
// $updateStmt->execute();
|
|
// }
|
|
|
|
// } catch (PDOException $e) {
|
|
// echo '<div class="alert alert-danger">Error: ' . $e->getMessage() . '</div>';
|
|
// }
|
|
// }
|
|
|
|
|
|
try {
|
|
$stmt = $db->prepare("SELECT * FROM invoice WHERE customerId = :customerId AND invoiceId = :invoiceId");
|
|
$stmt->bindParam(':invoiceId', $_GET['invoiceId']);
|
|
$stmt->bindParam(':customerId', $_GET['customerId']);
|
|
$stmt->execute();
|
|
$invoiceData = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
$stmt2 = $db->prepare("SELECT * FROM emi WHERE customerId = :customerId");
|
|
$stmt2->bindParam(':customerId', $_GET['customerId']);
|
|
$stmt2->execute();
|
|
$emiData = $stmt2->fetch(PDO::FETCH_ASSOC);
|
|
|
|
// var_dump($emiData);
|
|
} catch (PDOException $e) {
|
|
echo '<div class="alert alert-danger">Error: ' . $e->getMessage() . '</div>';
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['emiId'], $_POST['payStatus'], )) {
|
|
header('Content-Type: application/json');
|
|
ob_end_clean(); // Clears any accidental HTML output
|
|
try {
|
|
$stmt = $db->prepare("UPDATE emi SET payStatus = :payStatus, paymentDate = :paymentDate WHERE customerId = :customerId AND id = :emiId");
|
|
$stmt->bindParam(':customerId', $_GET['customerId']);
|
|
$stmt->bindParam(':payStatus', $_POST['payStatus'], PDO::PARAM_INT);
|
|
$stmt->bindParam(':emiId', $_POST['emiId'], PDO::PARAM_INT);
|
|
$stmt->bindParam(':paymentDate', $_POST['paymentDate']);
|
|
$stmt->execute();
|
|
|
|
// Ensure no previous output before JSON
|
|
echo json_encode(['status' => 'success']);
|
|
exit; // Terminate script after sending JSON
|
|
} catch (PDOException $e) {
|
|
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
try {
|
|
// Fetch EMI data
|
|
$stmt = $db->prepare("SELECT * FROM emi WHERE customerId = :customerId AND invoiceId = :invoiceId ORDER BY emiDate ASC");
|
|
$stmt->bindParam(':customerId', $_GET['customerId']);
|
|
$stmt->bindParam(':invoiceId', $_GET['invoiceId']);
|
|
$stmt->execute();
|
|
$emiPlans = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
// var_dump($emiPlans);
|
|
|
|
$stmt = $db->prepare("SELECT * FROM customers WHERE customerId = :customerId");
|
|
$stmt->bindParam(':customerId', $_GET['customerId']);
|
|
$stmt->execute();
|
|
$customer = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
// var_dump($customer);
|
|
|
|
} catch (PDOException $e) {
|
|
die('<div class="alert alert-danger text-center">Error: ' . $e->getMessage() . '</div>');
|
|
}
|
|
|
|
$currentOutstanding = 0;
|
|
$totalAmount = 0;
|
|
$bookingDate = null;
|
|
$currentOutstanding = 0;
|
|
$totalAmount = 0;
|
|
$bookingDate = null;
|
|
$tenure = null;
|
|
$frequency = null;
|
|
|
|
foreach ($emiPlans as $emi) {
|
|
$totalAmount = $emi['totalAmount'];
|
|
if ($bookingDate === null && !empty($emi['bookingDate'])) {
|
|
$bookingDate = $emi['bookingDate'];
|
|
}
|
|
if ($emi['payStatus'] == 0) {
|
|
$currentOutstanding += $emi['emiAmount'];
|
|
}
|
|
if ($tenure === null && isset($emi['tenure'])) {
|
|
$tenure = $emi['tenure'];
|
|
}
|
|
if ($frequency === null && isset($emi['frequency'])) {
|
|
$frequency = $emi['frequency'];
|
|
}
|
|
}
|
|
$currentOutstanding = round($currentOutstanding);
|
|
$tenure = $tenure !== null ? $tenure : 0;
|
|
$frequency = $frequency !== null ? $frequency : 0;
|
|
?>
|
|
<div class="container mt-4">
|
|
<div class="d-flex justify-content-between">
|
|
<h3 class="mb-3">Installment Details</h3>
|
|
<button type="button" class="btn text-white" data-bs-toggle="modal" data-bs-target="#myModal" style="background-color: #374151;">Additional Payment</button>
|
|
</div><hr/>
|
|
<div class="d-flex justify-content-between">
|
|
<div>
|
|
<p>Customer Name: <strong><?php echo $customer['name']; ?></strong></p>
|
|
<p>Mobile Number: <strong><?php echo $customer['mobile']; ?></strong></p>
|
|
<p>Installment Start Date: <strong><?php echo $bookingDate ? date("m/d/Y", strtotime($bookingDate)) : 'N/A'; ?></strong></p>
|
|
<p>Invoice Id: <strong><?php echo $emiPlans[0]['invoiceId']; ?></strong></p>
|
|
<p>Email: <strong><?php echo $customer['email']; ?></strong></p>
|
|
</div>
|
|
<div>
|
|
<p>Total Amount: <strong>$<?php echo $invoiceData['discountAmount'] + $totalAmount; ?></strong></p>
|
|
<p>Discount Amount: <strong>$<?php echo $invoiceData['discountAmount']; ?></strong></p>
|
|
<p>Effective Amount: <strong>$<?php echo $totalAmount; ?></strong></p>
|
|
<p>Outstanding: <strong>$<?php echo $currentOutstanding; ?></strong></p>
|
|
<p>Tenure: <strong><?php echo $tenure; ?></strong></p>
|
|
<p>Frequency: <strong><?php echo $invoiceData['frequency'] ?></strong></p>
|
|
</div>
|
|
</div>
|
|
<hr >
|
|
<div class="d-flex flex-column gap-3">
|
|
<table class="table table-striped table-bordered">
|
|
<thead class="text-white text-center" style="background-color: #374151;">
|
|
<tr>
|
|
<th>Installment</th>
|
|
<th>Amount</th>
|
|
<th>Date</th>
|
|
<th>Payment Date</th>
|
|
<th>Status</th>
|
|
<th>Action</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($emiPlans as $emi) {
|
|
if ($emi['emiAmount'] !== null) { ?>
|
|
<tr id="row-<?= $emi['id']; ?>">
|
|
<td><?= $emi['emiNumber']; ?></td>
|
|
<td>$<?= number_format($emi['emiAmount'], 2); ?></td>
|
|
<td><?= date("m/d/Y", strtotime($emi['emiDate'])); ?></td>
|
|
<td>
|
|
<?php if (!empty($emi['paymentDate'])) { ?>
|
|
<?= date("m/d/Y", strtotime($emi['paymentDate'])); ?>
|
|
<?php } else { ?>
|
|
<input value="<?= date('Y-m-d', strtotime($emi['emiDate'])); ?>" id="paymentDateId" class="form-control" type="date" />
|
|
<?php } ?>
|
|
</td>
|
|
<td class="text-center">
|
|
<span id="status-<?= $emi['id']; ?>" class="badge <?= $emi['payStatus'] == 0 ? 'bg-danger' : 'bg-success'; ?>">
|
|
<?= $emi['payStatus'] == 0 ? 'Unpaid' : 'Paid'; ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<select class="form-select paymentStatus" data-emi-id="<?= $emi['id']; ?>">
|
|
<option value="1" <?= $emi['payStatus'] == 1 ? 'selected' : ''; ?>>Paid</option>
|
|
<option value="0" <?= $emi['payStatus'] == 0 ? 'selected' : ''; ?>>Unpaid</option>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
<?php } } ?>
|
|
</tbody>
|
|
</table>
|
|
<h3 class="mb-3">Additional Payment Details</h3>
|
|
<table class="table table-striped table-bordered">
|
|
<thead class="text-white text-center" style="background-color: #374151;">
|
|
<tr>
|
|
<th>Amount</th>
|
|
<th>Payment Date</th>
|
|
<th>Transaction Id</th>
|
|
<th>Remarks</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($emiPlans as $emi) { if($emi['adPaymentAmount'] !== null) { ?>
|
|
<tr id="row-<?= $emi['id']; ?>">
|
|
<td>$<?= $emi['adPaymentAmount']; ?></td>
|
|
<td><?= date("m/d/Y", strtotime($emi['adPaymentDate'])); ?></td>
|
|
<td><?= $emi['adPaymentTran']; ?></td>
|
|
<td><?= $emi['adPaymentRemarks']; ?></td>
|
|
</tr>
|
|
<?php } }?>
|
|
</tbody>
|
|
</table>
|
|
<div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="modalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered"> <!-- This centers the modal -->
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title fw-bold" id="modalLabel" style="color: #374151;">Additional Payment</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form method="POST" class="">
|
|
<div class="form-group">
|
|
<label for="adPaymentAmount">Payment Amount:</label>
|
|
<input oninput="addAutoAddRemarks();" type="text" id="adPaymentAmount" name="adPaymentAmount" class="form-control" value="<?= htmlspecialchars($emiData['emiAmount']); ?>" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="adPaymentDate">Payment Date:</label>
|
|
<input type="date" id="adPaymentDate" name="adPaymentDate" class="form-control" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="adPaymentTran">Transaction ID:</label>
|
|
<input type="text" id="adPaymentTran" name="adPaymentTran" class="form-control" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="adPaymentSource">Payment Source:</label>
|
|
<input type="text" id="adPaymentSource" name="adPaymentSource" class="form-control" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="adPaymentRemarks">Remarks:</label>
|
|
<input type="text" id="adPaymentRemarks" name="adPaymentRemarks" class="form-control" >
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn" data-bs-dismiss="modal" style="color: #374151; border: 2px solid #374151;">Close</button>
|
|
<button type="submit" name="additional-payment" class="btn btn-block mt-2 text-white" style="background-color: #374151; border: 2px solid #374151;">Save Payment</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
document.querySelectorAll(".paymentStatus").forEach(select => {
|
|
select.addEventListener("change", function () {
|
|
let row = this.closest("tr");
|
|
let emiId = this.getAttribute("data-emi-id");
|
|
let newStatus = this.value;
|
|
let paymentDateInput = row.querySelector("#paymentDateId");
|
|
let paymentDate = paymentDateInput ? paymentDateInput.value : "";
|
|
|
|
fetch(window.location.href, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
body: `emiId=${emiId}&payStatus=${newStatus}&paymentDate=${paymentDate}`
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
console.log(data); // Debugging output
|
|
if (data.status === "success") {
|
|
let statusBadge = document.getElementById("status-" + emiId);
|
|
if (statusBadge) {
|
|
statusBadge.textContent = newStatus == 1 ? "Paid" : "Unpaid";
|
|
statusBadge.className = "badge " + (newStatus == 1 ? "bg-success" : "bg-danger");
|
|
}
|
|
} else {
|
|
alert("Error updating status: " + data.message);
|
|
}
|
|
})
|
|
.catch(error => console.error("Error:", error));
|
|
});
|
|
});
|
|
});
|
|
|
|
function addAutoAddRemarks() {
|
|
const emiAmount = <?= json_encode($emiData['emiAmount']); ?>;
|
|
const addPayAmount = parseFloat(document.getElementById('adPaymentAmount').value) || 0;
|
|
const extraAmount = addPayAmount - emiAmount;
|
|
|
|
document.getElementById('adPaymentRemarks').value =
|
|
`EMI Amount: ${emiAmount}. Extra ${extraAmount > 0 ? extraAmount.toFixed(2) : "0.00"} Settled in last EMI `;
|
|
}
|
|
|
|
// document.getElementById('paymentDateId').value = new Date();
|
|
|
|
|
|
|
|
</script>
|