Implement Phase 2 features: roles, assessment groups, budget import, Kanban
- Add hierarchical roles: SuperUser Admin (is_superadmin flag), Tenant Admin, Tenant User with separate /admin route and admin panel - Add Assessment Groups module for property type-based assessment rates (SFHs, Condos, Estate Lots with different regular/special rates) - Enhance Chart of Accounts: initial balance on create (with journal entry), archive/restore accounts, edit all fields including account number & fund type - Add Budget CSV import with downloadable template and account mapping - Add Capital Projects Kanban board with drag-and-drop between year columns, table/kanban view toggle, and PDF export via browser print - Update seed data with assessment groups, second test user, superadmin flag - Create repeatable reseed.sh script for clean database population - Fix AgingReportPage Mantine v7 Table prop compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,14 +48,15 @@ BEGIN
|
||||
-- Check if user exists
|
||||
SELECT id INTO v_user_id FROM shared.users WHERE email = 'admin@sunrisevalley.org';
|
||||
IF v_user_id IS NULL THEN
|
||||
INSERT INTO shared.users (id, email, password_hash, first_name, last_name)
|
||||
INSERT INTO shared.users (id, email, password_hash, first_name, last_name, is_superadmin)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'admin@sunrisevalley.org',
|
||||
-- bcrypt hash of 'password123'
|
||||
'$2b$10$1mtM00QBNQpAsyopajk3BeFY5DdxksvRYuM1E8qB.ePjCIYkfHMHO',
|
||||
'Sarah',
|
||||
'Johnson'
|
||||
'Johnson',
|
||||
true
|
||||
) RETURNING id INTO v_user_id;
|
||||
END IF;
|
||||
|
||||
@@ -78,6 +79,26 @@ IF v_org_id IS NULL THEN
|
||||
VALUES (v_user_id, v_org_id, 'president');
|
||||
END IF;
|
||||
|
||||
-- Create a second test user (viewer/homeowner)
|
||||
DECLARE v_viewer_id UUID;
|
||||
BEGIN
|
||||
SELECT id INTO v_viewer_id FROM shared.users WHERE email = 'viewer@sunrisevalley.org';
|
||||
IF v_viewer_id IS NULL THEN
|
||||
INSERT INTO shared.users (id, email, password_hash, first_name, last_name, is_superadmin)
|
||||
VALUES (
|
||||
uuid_generate_v4(),
|
||||
'viewer@sunrisevalley.org',
|
||||
'$2b$10$1mtM00QBNQpAsyopajk3BeFY5DdxksvRYuM1E8qB.ePjCIYkfHMHO',
|
||||
'Mike',
|
||||
'Resident',
|
||||
false
|
||||
) RETURNING id INTO v_viewer_id;
|
||||
|
||||
INSERT INTO shared.user_organizations (user_id, organization_id, role)
|
||||
VALUES (v_viewer_id, v_org_id, 'homeowner');
|
||||
END IF;
|
||||
END;
|
||||
|
||||
-- ============================================================
|
||||
-- 2. Create tenant schema (if not exists)
|
||||
-- ============================================================
|
||||
@@ -147,6 +168,19 @@ CREATE TABLE IF NOT EXISTS %I.journal_entry_lines (
|
||||
memo TEXT
|
||||
)', v_schema);
|
||||
|
||||
EXECUTE format('
|
||||
CREATE TABLE IF NOT EXISTS %I.assessment_groups (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
regular_assessment DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
special_assessment DECIMAL(10,2) DEFAULT 0.00,
|
||||
unit_count INTEGER DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
)', v_schema);
|
||||
|
||||
EXECUTE format('
|
||||
CREATE TABLE IF NOT EXISTS %I.units (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
@@ -164,6 +198,7 @@ CREATE TABLE IF NOT EXISTS %I.units (
|
||||
owner_phone VARCHAR(20),
|
||||
is_rented BOOLEAN DEFAULT FALSE,
|
||||
monthly_assessment DECIMAL(10,2),
|
||||
assessment_group_id UUID,
|
||||
status VARCHAR(20) DEFAULT ''active'',
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
@@ -314,6 +349,7 @@ EXECUTE format('DELETE FROM %I.investment_accounts', v_schema);
|
||||
EXECUTE format('DELETE FROM %I.reserve_components', v_schema);
|
||||
EXECUTE format('DELETE FROM %I.vendors', v_schema);
|
||||
EXECUTE format('DELETE FROM %I.units', v_schema);
|
||||
EXECUTE format('DELETE FROM %I.assessment_groups', v_schema);
|
||||
EXECUTE format('DELETE FROM %I.fiscal_periods', v_schema);
|
||||
EXECUTE format('DELETE FROM %I.accounts', v_schema);
|
||||
|
||||
@@ -376,6 +412,15 @@ FOR v_month IN 1..12 LOOP
|
||||
USING v_year - 1, v_month, 'closed';
|
||||
END LOOP;
|
||||
|
||||
-- ============================================================
|
||||
-- 4b. Seed Assessment Groups
|
||||
-- ============================================================
|
||||
EXECUTE format('INSERT INTO %I.assessment_groups (name, description, regular_assessment, special_assessment, unit_count) VALUES
|
||||
(''Single Family Homes'', ''Standard single family detached homes (Units 1-20)'', 350.00, 0.00, 20),
|
||||
(''Patio Homes'', ''Medium-sized patio homes (Units 21-35)'', 425.00, 0.00, 15),
|
||||
(''Estate Lots'', ''Large estate lots (Units 36-50)'', 500.00, 75.00, 15)
|
||||
', v_schema);
|
||||
|
||||
-- ============================================================
|
||||
-- 5. Seed 50 units
|
||||
-- ============================================================
|
||||
@@ -394,17 +439,26 @@ DECLARE
|
||||
'Mitchell','Carter','Roberts'];
|
||||
v_unit_num INT;
|
||||
v_assess NUMERIC;
|
||||
v_ag_id UUID;
|
||||
v_ag_name TEXT;
|
||||
BEGIN
|
||||
FOR v_unit_num IN 1..50 LOOP
|
||||
-- Vary assessment based on unit size
|
||||
v_assess := CASE
|
||||
WHEN v_unit_num <= 20 THEN 350.00 -- standard
|
||||
WHEN v_unit_num <= 35 THEN 425.00 -- medium
|
||||
ELSE 500.00 -- large
|
||||
END;
|
||||
-- Vary assessment based on unit size and assign assessment group
|
||||
IF v_unit_num <= 20 THEN
|
||||
v_assess := 350.00;
|
||||
v_ag_name := 'Single Family Homes';
|
||||
ELSIF v_unit_num <= 35 THEN
|
||||
v_assess := 425.00;
|
||||
v_ag_name := 'Patio Homes';
|
||||
ELSE
|
||||
v_assess := 500.00;
|
||||
v_ag_name := 'Estate Lots';
|
||||
END IF;
|
||||
|
||||
EXECUTE format('INSERT INTO %I.units (unit_number, address_line1, city, state, zip_code, owner_name, owner_email, owner_phone, monthly_assessment, square_footage)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)', v_schema)
|
||||
EXECUTE format('SELECT id FROM %I.assessment_groups WHERE name = $1', v_schema) INTO v_ag_id USING v_ag_name;
|
||||
|
||||
EXECUTE format('INSERT INTO %I.units (unit_number, address_line1, city, state, zip_code, owner_name, owner_email, owner_phone, monthly_assessment, square_footage, assessment_group_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)', v_schema)
|
||||
USING
|
||||
LPAD(v_unit_num::TEXT, 3, '0'),
|
||||
(100 + v_unit_num * 2)::TEXT || ' Sunrise Valley Drive',
|
||||
@@ -413,7 +467,8 @@ BEGIN
|
||||
LOWER(v_first_names[v_unit_num]) || '.' || LOWER(v_last_names[v_unit_num]) || '@email.com',
|
||||
'(480) 555-' || LPAD((1000 + v_unit_num)::TEXT, 4, '0'),
|
||||
v_assess,
|
||||
CASE WHEN v_unit_num <= 20 THEN 1200 WHEN v_unit_num <= 35 THEN 1600 ELSE 2000 END;
|
||||
CASE WHEN v_unit_num <= 20 THEN 1200 WHEN v_unit_num <= 35 THEN 1600 ELSE 2000 END,
|
||||
v_ag_id;
|
||||
END LOOP;
|
||||
END;
|
||||
|
||||
@@ -779,6 +834,7 @@ EXECUTE format('INSERT INTO %I.capital_projects (name, description, estimated_co
|
||||
', v_schema) USING v_year;
|
||||
|
||||
RAISE NOTICE 'Seed data created successfully for Sunrise Valley HOA!';
|
||||
RAISE NOTICE 'Login: admin@sunrisevalley.org / password123';
|
||||
RAISE NOTICE 'Admin Login: admin@sunrisevalley.org / password123 (SuperAdmin + President)';
|
||||
RAISE NOTICE 'Viewer Login: viewer@sunrisevalley.org / password123 (Homeowner)';
|
||||
|
||||
END $$;
|
||||
|
||||
Reference in New Issue
Block a user