From 62071c664558bf75b8749ddcfe1c50eab499dd80 Mon Sep 17 00:00:00 2001 From: Keith Solomon Date: Sun, 9 Feb 2025 12:02:00 -0600 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feature:=20Update=20database=20schema?= =?UTF-8?q?=20to=20separate=20payees=20from=20payments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + data/bills-sample.db | Bin 8192 -> 20480 bytes includes/api.php | 79 +++++++++++++++++++++++++++++-------------- includes/db.php | 23 ++++++++----- index.php | 2 +- js/app.js | 16 +++------ 6 files changed, 74 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 63b360f..ebbed9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +Temp/ node_modules/ *-bak* bills.db diff --git a/data/bills-sample.db b/data/bills-sample.db index 87b17424ef2e0514f110df190e9151c924cc5182..5bf797d12c2ff5b0b0c06f6e17ea3c22a88684c1 100644 GIT binary patch literal 20480 zcmeI%L2ueH7zSX6(sruE=wVXC?K^^~Doxvc^Ma|OhCqWOl@m(AlOmC@LXg_ys{OKE z_lI_z?EoF^cIlD6mh9M0?D%_34i>|!AT1PqoiDPapbzYnIS%_w#2BmSe5ms#nRa#4 z&{yZL`v0mGc0OUX`fpaP6|DZQ{_E{eT|t5X1Rwwb2tWV=5P$##An-~A9xkiLuIoBK zRz-3%Q#a{swzS2e7YQx}N&Y1eWV@(YJ0Y9WDfyuk7b2oTVZ8G z%CpVGW^5gc;X4kUSTq;=$2`aLm}yf;`wv@1vMr-sAQ ze5&r&!6mC=ZrkH>t>gFQ^+11WZ_MXbGsUSXkRSj72tWV=5P$##AOHafKmY;|*jIrQ z6By3_`?|e|3jz>;00bZa0SG_<0uX=z1R!7q@c%!42oQh(1Rwwb2tWV=5P$##AOL~= f7r^;{|MwUXLI45~fB*y_009U<00Izz00jO3YV*Fd delta 167 zcmZozz}Vn0L0XWJfq{Vuh+%+nqK+{?BZFQt120gBk?#is-;d3L0$qGkO{|RU;^N|r z&6y>MNja%WnK?PdV1j9KAFqt8fwFCpkHePeEKkAvr%cH#M(BA;dKz1f&53G#3d7008fC BC&2&! diff --git a/includes/api.php b/includes/api.php index 26fc76a..1edbec2 100644 --- a/includes/api.php +++ b/includes/api.php @@ -18,15 +18,27 @@ try { switch($action) { case 'add': $data = [ - 'date' => (new DateTime($_POST['date']))->format('Y-m-d'), // Normalize to YYYY-MM-DD - 'billName' => $_POST['billName'], - 'amount' => (float)$_POST['amount'], + 'date' => (new DateTime($_POST['date']))->format('Y-m-d'), + 'payeeId' => $_POST['payeeId'], // Payee ID instead of name + 'amount' => (float)$_POST['amount'], 'paymentId' => $_POST['paymentId'], - 'year' => (int)explode('-', $_POST['date'])[0], - 'comment' => $_POST['comment'] + 'comment' => $_POST['comment'] ?? '', + 'year' => (int)explode('-', $_POST['date'])[0] ]; - $result = Bill::add($data); + $stmt = DB::connect()->prepare(" + INSERT INTO bills (billDate, payeeId, amount, paymentId, comment, year) + VALUES (?, ?, ?, ?, ?, ?) + "); + $result = $stmt->execute([ + $data['date'], + $data['payeeId'], + $data['amount'], + $data['paymentId'], + $data['comment'], + $data['year'] + ]); + echo json_encode(['success' => $result]); break; @@ -75,17 +87,6 @@ try { } break; - case 'getPayees': - $stmt = DB::connect()->query("SELECT DISTINCT billName FROM bills ORDER BY billName ASC"); - echo json_encode($stmt->fetchAll(PDO::FETCH_COLUMN)); - break; - - case 'addPayee': - $stmt = DB::connect()->prepare("INSERT INTO bills (billName) VALUES (?)"); - $result = $stmt->execute([$_POST['billName']]); - echo json_encode(['success' => $result]); - break; - case 'getAll': echo json_encode(Bill::getAll()->fetchAll(PDO::FETCH_ASSOC)); break; @@ -97,30 +98,56 @@ try { echo json_encode($stmt->fetch(PDO::FETCH_ASSOC)); break; - case 'getTotals': + case 'getTotals': echo json_encode(Bill::getYearlyTotals()->fetchAll(PDO::FETCH_ASSOC)); break; case 'getByYear': $year = $_GET['year'] ?? date('Y'); - $sort = $_GET['sort'] ?? 'date_asc'; // Default sorting + $sort = $_GET['sort'] ?? 'date_desc'; $sortOptions = [ - 'date_asc' => 'billDate ASC', - 'date_desc' => 'billDate DESC', - 'payee' => 'billName ASC, billDate ASC', + 'date_asc' => 'bills.billDate ASC', + 'date_desc' => 'bills.billDate DESC', + 'payee' => 'payees.name ASC, bills.billDate ASC' ]; - $orderBy = $sortOptions[$sort] ?? $sortOptions['date_asc']; - $stmt = DB::connect()->prepare("SELECT * FROM bills WHERE year = ? ORDER BY $orderBy"); + $stmt = DB::connect()->prepare(" + SELECT bills.*, payees.name AS payeeName + FROM bills + JOIN payees ON bills.payeeId = payees.id + WHERE bills.year = ? + ORDER BY $orderBy + "); $stmt->execute([$year]); echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)); break; + case 'addPayee': + $stmt = DB::connect()->prepare("INSERT INTO payees (name) VALUES (?)"); + $result = $stmt->execute([$_POST['payeeName']]); + echo json_encode(['success' => $result]); + break; + + case 'getPayees': + try { + $stmt = DB::connect()->query("SELECT id, name FROM payees ORDER BY name ASC"); + $payees = $stmt->fetchAll(PDO::FETCH_ASSOC); + echo json_encode($payees); + } catch (Exception $e) { + echo json_encode(['error' => $e->getMessage()]); + } + break; + case 'getYears': - $stmt = DB::connect()->query("SELECT DISTINCT year FROM bills ORDER BY year DESC"); - echo json_encode($stmt->fetchAll(PDO::FETCH_COLUMN)); + try { + $stmt = DB::connect()->query("SELECT DISTINCT year FROM bills ORDER BY year DESC"); + $years = $stmt->fetchAll(PDO::FETCH_COLUMN); + echo json_encode($years); + } catch (Exception $e) { + echo json_encode(['error' => $e->getMessage()]); + } break; default: diff --git a/includes/db.php b/includes/db.php index 938ba43..85aeaf6 100644 --- a/includes/db.php +++ b/includes/db.php @@ -3,15 +3,22 @@ class DB { public static function connect() { $db = new PDO('sqlite:'.__DIR__.'/../data/bills.db'); + $db->exec("CREATE TABLE IF NOT EXISTS payees ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE, + createdAt TEXT DEFAULT CURRENT_TIMESTAMP + )"); + $db->exec("CREATE TABLE IF NOT EXISTS bills ( - id INTEGER PRIMARY KEY, - billDate TEXT NOT NULL, - billName TEXT NOT NULL, - amount REAL NOT NULL, - paymentId TEXT, - year INTEGER NOT NULL, - comment TEXT - )"); + id INTEGER PRIMARY KEY AUTOINCREMENT, + billDate TEXT NOT NULL, + payeeId INTEGER NOT NULL, + amount REAL NOT NULL, + paymentId TEXT, + comment TEXT, + year INTEGER NOT NULL, + FOREIGN KEY (payeeId) REFERENCES payees(id) ON DELETE CASCADE + )"); return $db; } diff --git a/index.php b/index.php index a2571fe..5733fe0 100644 --- a/index.php +++ b/index.php @@ -41,7 +41,7 @@

Add New Payee

- +
diff --git a/js/app.js b/js/app.js index e4bacd0..a764428 100644 --- a/js/app.js +++ b/js/app.js @@ -31,21 +31,13 @@ document.addEventListener('DOMContentLoaded', () => { const response = await fetch('/includes/api.php?action=getPayees'); const payees = await response.json(); - const payeeSelect = document.getElementById('editFormBillName'); + const payeeSelect = document.getElementById('billName'); payeeSelect.innerHTML = ''; // Clear existing options - // Add default "Select Payee" option - const defaultOption = document.createElement('option'); - defaultOption.value = ''; - defaultOption.textContent = 'Select Payee'; - defaultOption.disabled = true; - payeeSelect.appendChild(defaultOption); - - // Populate payees payees.forEach(payee => { const option = document.createElement('option'); - option.value = payee; - option.textContent = payee; + option.value = payee.id; // Use payee ID as the value + option.textContent = payee.name; // Display payee name payeeSelect.appendChild(option); }); } @@ -77,7 +69,7 @@ document.addEventListener('DOMContentLoaded', () => { billItem.innerHTML = `

Date: ${formattedDate}

-

Bill Name: ${bill.billName}

+

Bill Name: ${bill.payeeName}

Amount: $${bill.amount.toFixed(2)}

Payment ID: ${bill.paymentId || 'N/A'}

Comment: ${bill.comment || 'N/A'}