« Back to History
party_payment.php
|
20260721_154033.php
Initial Bulk Import
Copy Code
<?php /* ============================================================================= File: /erp/party_payment.php Purpose: Save Party Bank Payment (Excel Auto Download Enabled) ============================================================================= */ header('X-Frame-Options: SAMEORIGIN'); require_once __DIR__ . '/modules/auth/page_acl.php'; require_once __DIR__ . '/helpers/activity_helper.php'; $ctx = page_require_access('party_payment'); $u = $ctx['user'] ?? null; $company_id = (int)($ctx['company_id'] ?? 0); $pdo = $ctx['pdo']; $user_id = (int)($u['id'] ?? 0); function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } $success = ''; $error = ''; function build_export_rows(float $company_limit, int $account_id, float $amount, string $remark): array { $export_rows = []; if ($company_limit > 0 && $amount > $company_limit) { $remaining = $amount; while ($remaining > 0) { $part = min($company_limit, $remaining); $export_rows[] = [ 'party_account_id' => $account_id, 'amount' => $part, 'remark' => $remark, ]; $remaining -= $part; } } else { $export_rows[] = [ 'party_account_id' => $account_id, 'amount' => $amount, 'remark' => $remark, ]; } return $export_rows; } function render_export_form(array $export_rows): void { $export_data = [ 'rows' => $export_rows, 'fmt' => 'xlsx', ]; ?> <form id="autoExport" method="post" action="party_payment_export.php"> <input type="hidden" name="export_json" value='<?= h(json_encode($export_data)) ?>'> </form> <script> document.getElementById('autoExport').submit(); </script> <?php exit; } /* ===================== COMPANY NEFT LIMIT ===================== */ $limit_st = $pdo->prepare(" SELECT neft_limit FROM company_bank_accounts WHERE company_id = ? LIMIT 1 "); $limit_st->execute([$company_id]); $company_limit = (float)($limit_st->fetchColumn() ?: 0); /* ===================== REGENERATE EXPORT ===================== */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'regenerate_payment_file') { $payment_id = (int)($_POST['payment_id'] ?? 0); if ($payment_id <= 0) { $error = 'Invalid payment selected.'; } else { $st = $pdo->prepare(" SELECT id, person_id, amount, remark FROM payments WHERE id = ? AND company_id = ? AND person_type = 'party' AND payment_type = 'party_payment' LIMIT 1 "); $st->execute([$payment_id, $company_id]); $payment = $st->fetch(PDO::FETCH_ASSOC); if (!$payment) { $error = 'Payment record not found.'; } else { $account_st = $pdo->prepare(" SELECT id FROM party_ac_detail WHERE id = ? AND company_id = ? AND COALESCE(is_active,1)=1 LIMIT 1 "); $account_st->execute([(int)$payment['person_id'], $company_id]); if (!$account_st->fetchColumn()) { $error = 'Linked party account is inactive or missing.'; } else { $export_rows = build_export_rows( $company_limit, (int)$payment['person_id'], (float)$payment['amount'], trim((string)($payment['remark'] ?? '')) ); activity_create('report', 'excel_export', 0, 'Export generated'); render_export_form($export_rows); } } } } /* ===================== AJAX: Load Accounts ===================== */ if (isset($_GET['ajax']) && $_GET['ajax'] === 'party_accounts') { $party = trim($_GET['party_name'] ?? ''); $st = $pdo->prepare(" SELECT id, bank_name, account_no, beneficiary_name, ifsc_code FROM party_ac_detail WHERE company_id = ? AND party_name = ? AND COALESCE(is_active,1)=1 "); $st->execute([$company_id, $party]); header('Content-Type: application/json'); echo json_encode($st->fetchAll(PDO::FETCH_ASSOC)); exit; } /* ===================== SAVE LOGIC ===================== */ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $account_id = (int)($_POST['party_account_id'] ?? 0); $amount = (float)($_POST['amount'] ?? 0); $pay_date = $_POST['payment_date'] ?? date('Y-m-d'); $remark = trim($_POST['remark'] ?? ''); if ($account_id <= 0) { $error = "Please select valid party account."; } elseif ($amount <= 0) { $error = "Amount must be greater than zero."; } else { $st = $pdo->prepare(" SELECT id, party_name FROM party_ac_detail WHERE id = ? AND company_id = ? AND COALESCE(is_active,1)=1 LIMIT 1 "); $st->execute([$account_id, $company_id]); $party = $st->fetch(PDO::FETCH_ASSOC); if (!$party) { $error = "Invalid party account."; } else { try { $pdo->beginTransaction(); $ins = $pdo->prepare(" INSERT INTO payments (company_id, person_type, person_id, payment_type, amount, payment_date, payment_mode, remark, created_by, created_at) VALUES (?, 'party', ?, 'party_payment', ?, ?, 'BANK', ?, ?, NOW()) "); $ins->execute([ $company_id, $account_id, $amount, $pay_date, $remark, $user_id ]); $insert_id = (int)$pdo->lastInsertId(); $pdo->commit(); activity_create('payment', 'party_payment', $insert_id ?? 0, 'Party payment created'); $export_rows = build_export_rows($company_limit, $account_id, $amount, $remark); activity_create('report', 'excel_export', 0, 'Export generated'); render_export_form($export_rows); } catch (Exception $e) { $pdo->rollBack(); $error = "Database error: " . $e->getMessage(); } } } } require_once __DIR__ . '/partials/header.php'; ?> <div class="container-fluid py-4"> <div class="row justify-content-center"> <div class="col-lg-10"> <div class="d-flex align-items-center mb-4"> <h4 class="mb-0 fw-bold text-primary"> <i class="bi bi-cash-stack me-2"></i>Party Bank Payment </h4> </div> <?php if ($error): ?> <div class="alert alert-danger"><?= h($error) ?></div> <?php endif; ?> <div class="card border-0 shadow-sm"> <div class="card-body p-4"> <form method="post"> <div class="row g-3"> <div class="col-md-3"> <label class="form-label small fw-bold text-muted">SELECT PARTY *</label> <select name="party_name" id="partySelect" class="form-select" required> <option value="">-- Select Party --</option> <?php $parties = $pdo->prepare(" SELECT DISTINCT party_name FROM party_ac_detail WHERE company_id = ? AND COALESCE(is_active,1)=1 ORDER BY party_name "); $parties->execute([$company_id]); foreach ($parties->fetchAll(PDO::FETCH_COLUMN) as $p): ?> <option value="<?= h($p) ?>"><?= h($p) ?></option> <?php endforeach; ?> </select> </div> <div class="col-md-3"> <label class="form-label small fw-bold text-muted">BANK ACCOUNT *</label> <select name="party_account_id" id="accountSelect" class="form-select" required> <option value="">-- First Select Party --</option> </select> </div> <div class="col-md-2"> <label class="form-label small fw-bold text-muted">AMOUNT *</label> <div class="input-group"> <span class="input-group-text">₹</span> <input type="number" step="0.01" name="amount" id="amountInput" class="form-control" required> </div> <?php if($company_limit > 0): ?> <div class="small text-muted mt-1"> Company NEFT Limit: <strong>₹<?= number_format($company_limit,2) ?></strong> </div> <?php endif; ?> <div class="small text-primary mt-1"> Amount in Words: <strong id="amountWords">Zero</strong> </div> </div> <div class="col-md-4"> <label class="form-label small fw-bold text-muted">REMARK</label> <input type="text" name="remark" class="form-control"> </div> <input type="hidden" name="payment_date" value="<?= date('Y-m-d') ?>"> </div> <div class="mt-4 text-end"> <button type="submit" class="btn btn-primary px-5"> <i class="bi bi-file-earmark-excel me-2"></i>Save & Download Excel </button> </div> </form> </div> </div> <div id="accountInfo" class="mt-3 d-none"> <div class="alert alert-info small py-2 px-3 d-inline-block"> <strong>Beneficiary:</strong> <span id="info_ben"></span> | <strong>IFSC:</strong> <span id="info_ifsc"></span> </div> </div> </div> </div> </div> <script> /* ===================== PARTY ACCOUNT LOAD ===================== */ document.getElementById('partySelect').addEventListener('change', function() { const partyName = this.value; const accountSelect = document.getElementById('accountSelect'); const infoBox = document.getElementById('accountInfo'); if(!partyName){ accountSelect.innerHTML = '<option value="">-- First Select Party --</option>'; infoBox.classList.add('d-none'); return; } fetch(`party_payment.php?ajax=party_accounts&party_name=${encodeURIComponent(partyName)}`) .then(r => r.json()) .then(list => { let opt = '<option value="">Select Account</option>'; list.forEach(a => { opt += `<option value="${a.id}" data-ben="${a.beneficiary_name}" data-ifsc="${a.ifsc_code}"> ${a.bank_name} - ${a.account_no} </option>`; }); accountSelect.innerHTML = opt; }); }); document.getElementById('accountSelect').addEventListener('change', function() { const selected = this.options[this.selectedIndex]; const infoBox = document.getElementById('accountInfo'); if(this.value){ document.getElementById('info_ben').innerText = selected.getAttribute('data-ben'); document.getElementById('info_ifsc').innerText = selected.getAttribute('data-ifsc'); infoBox.classList.remove('d-none'); } else{ infoBox.classList.add('d-none'); } }); /* ===================== AMOUNT IN WORDS ===================== */ function numberToWords(num){ const a=["","One","Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten","Eleven","Twelve","Thirteen","Fourteen","Fifteen","Sixteen","Seventeen","Eighteen","Nineteen"]; const b=["","","Twenty","Thirty","Forty","Fifty","Sixty","Seventy","Eighty","Ninety"]; function inWords(n){ if(n<20) return a[n]; if(n<100) return b[Math.floor(n/10)]+" "+a[n%10]; if(n<1000) return a[Math.floor(n/100)]+" Hundred "+inWords(n%100); if(n<100000) return inWords(Math.floor(n/1000))+" Thousand "+inWords(n%1000); if(n<10000000) return inWords(Math.floor(n/100000))+" Lakh "+inWords(n%100000); return inWords(Math.floor(n/10000000))+" Crore "+inWords(n%10000000); } return inWords(num); } document.getElementById('amountInput').addEventListener('input',function(){ let val=parseInt(this.value||0); document.getElementById('amountWords').innerText= numberToWords(val)+" Rupees Only"; }); </script> <?php require_once __DIR__ . '/partials/footer.php'; ?>