feat(extraordinary-expenses): Add module for extraordinary expenses
Introduces a new module to manage and track extraordinary expenses within condominiums. This includes defining expense items, sharing arrangements, and attaching relevant documents. The module adds new types for `ExpenseItem`, `ExpenseShare`, and `ExtraordinaryExpense`. Mock database functions are updated to support fetching, creating, and managing these expenses. UI components in `Layout.tsx` and `Settings.tsx` are modified to include navigation and feature toggling for extraordinary expenses. Additionally, new routes are added in `App.tsx` for both administrative and user-facing views of these expenses.
This commit is contained in:
62
server/db.js
62
server/db.js
@@ -46,7 +46,12 @@ const dbInterface = {
|
||||
if (DB_CLIENT === 'postgres') {
|
||||
return {
|
||||
query: executeQuery,
|
||||
release: () => {}
|
||||
release: () => {},
|
||||
// Mock transaction methods for Postgres simple wrapper
|
||||
// In a real prod app, you would get a specific client from the pool here
|
||||
beginTransaction: async () => {},
|
||||
commit: async () => {},
|
||||
rollback: async () => {}
|
||||
};
|
||||
} else {
|
||||
return await mysqlPool.getConnection();
|
||||
@@ -347,6 +352,58 @@ const initDb = async () => {
|
||||
)
|
||||
`);
|
||||
|
||||
// 11. Extraordinary Expenses Tables
|
||||
await connection.query(`
|
||||
CREATE TABLE IF NOT EXISTS extraordinary_expenses (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
condo_id VARCHAR(36) NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
start_date ${TIMESTAMP_TYPE},
|
||||
end_date ${TIMESTAMP_TYPE},
|
||||
contractor_name VARCHAR(255),
|
||||
total_amount DECIMAL(15, 2) DEFAULT 0,
|
||||
created_at ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (condo_id) REFERENCES condos(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
await connection.query(`
|
||||
CREATE TABLE IF NOT EXISTS expense_items (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
expense_id VARCHAR(36) NOT NULL,
|
||||
description VARCHAR(255),
|
||||
amount DECIMAL(15, 2) NOT NULL,
|
||||
FOREIGN KEY (expense_id) REFERENCES extraordinary_expenses(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
await connection.query(`
|
||||
CREATE TABLE IF NOT EXISTS expense_shares (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
expense_id VARCHAR(36) NOT NULL,
|
||||
family_id VARCHAR(36) NOT NULL,
|
||||
percentage DECIMAL(5, 2) NOT NULL,
|
||||
amount_due DECIMAL(15, 2) NOT NULL,
|
||||
amount_paid DECIMAL(15, 2) DEFAULT 0,
|
||||
status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
FOREIGN KEY (expense_id) REFERENCES extraordinary_expenses(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (family_id) REFERENCES families(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
await connection.query(`
|
||||
CREATE TABLE IF NOT EXISTS expense_attachments (
|
||||
id VARCHAR(36) PRIMARY KEY,
|
||||
expense_id VARCHAR(36) NOT NULL,
|
||||
file_name VARCHAR(255) NOT NULL,
|
||||
file_type VARCHAR(100),
|
||||
data ${LONG_TEXT_TYPE},
|
||||
created_at ${TIMESTAMP_TYPE} DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (expense_id) REFERENCES extraordinary_expenses(id) ON DELETE CASCADE
|
||||
)
|
||||
`);
|
||||
|
||||
// --- SEEDING ---
|
||||
const [rows] = await connection.query('SELECT * FROM settings WHERE id = 1');
|
||||
const defaultFeatures = {
|
||||
@@ -354,7 +411,8 @@ const initDb = async () => {
|
||||
tickets: true,
|
||||
payPal: true,
|
||||
notices: true,
|
||||
reports: true
|
||||
reports: true,
|
||||
extraordinaryExpenses: true
|
||||
};
|
||||
|
||||
if (rows.length === 0) {
|
||||
|
||||
Reference in New Issue
Block a user