next dev
This commit is contained in:
parent
cdc6e49414
commit
f7f6d6a23a
99
TODO.md
99
TODO.md
@ -0,0 +1,99 @@
|
|||||||
|
# Lease Approval Implementation Plan
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
Implement landlord approval mechanism for tenant invitation workflow. Currently, tenants can click "Start Lease" without landlord oversight. This plan adds proper approval workflow.
|
||||||
|
|
||||||
|
## Implementation Tasks
|
||||||
|
|
||||||
|
### 1. Database Schema Changes (HIGH PRIORITY)
|
||||||
|
- [ ] Add approval workflow fields to `leases` table:
|
||||||
|
- `approval_status` TEXT DEFAULT 'pending_approval'
|
||||||
|
- `approval_requested_at` BIGINT
|
||||||
|
- `approved_at` BIGINT
|
||||||
|
- `approved_by` TEXT REFERENCES users(id)
|
||||||
|
- `rejection_reason` TEXT
|
||||||
|
- [ ] Create migration SQL file
|
||||||
|
- [ ] Update database interfaces
|
||||||
|
|
||||||
|
### 2. API Endpoints (HIGH PRIORITY)
|
||||||
|
- [ ] Create `POST /api/lease/request-approval` - Tenant initiates lease
|
||||||
|
- [ ] Create `POST /api/lease/approve` - Landlord approval
|
||||||
|
- [ ] Create `POST /api/lease/reject` - Landlord rejection
|
||||||
|
- [ ] Create `GET /api/lease/pending-approvals` - Landlord dashboard
|
||||||
|
- [ ] Extend `leaseService.ts` with approval functions:
|
||||||
|
- `requestLeaseApproval()`
|
||||||
|
- `approveLease()`
|
||||||
|
- `rejectLease()`
|
||||||
|
- `getPendingApprovals()`
|
||||||
|
|
||||||
|
### 3. Lease Finalization Mechanism (HIGH PRIORITY)
|
||||||
|
- [ ] Implement lease activation on approval
|
||||||
|
- [ ] Ensure proper record linking (tenant_id, lease_id)
|
||||||
|
- [ ] Update tenant invite to reference approved lease
|
||||||
|
- [ ] Set up access rights and permissions
|
||||||
|
- [ ] Create payment schedules and reminders
|
||||||
|
- [ ] Validate data integrity
|
||||||
|
|
||||||
|
### 4. Tenant Invitation Page Updates (MEDIUM PRIORITY)
|
||||||
|
- [ ] Update `/tenant/invite/[invite_id].tsx` to check lease status
|
||||||
|
- [ ] Add status-based UI states:
|
||||||
|
- No lease: "Start Lease" button
|
||||||
|
- Pending: "Pending Landlord Approval"
|
||||||
|
- Approved: "Lease Approved - Continue"
|
||||||
|
- Rejected: "Lease Rejected" with contact info
|
||||||
|
- [ ] Add progress indicator showing approval steps
|
||||||
|
- [ ] Update POST handler to call approval API
|
||||||
|
|
||||||
|
### 5. Landlord Notifications (MEDIUM PRIORITY)
|
||||||
|
- [ ] Create `notificationService.ts` for centralized notifications
|
||||||
|
- [ ] Implement email templates:
|
||||||
|
- "New Lease Approval Required"
|
||||||
|
- "Lease Approved" confirmation
|
||||||
|
- "Lease Rejected" confirmation
|
||||||
|
- [ ] Add dashboard notifications
|
||||||
|
- [ ] Integrate with user preference system
|
||||||
|
|
||||||
|
### 6. Landlord Dashboard View (MEDIUM PRIORITY)
|
||||||
|
- [ ] Add "Pending Lease Approvals" section to dashboard
|
||||||
|
- [ ] Create approval cards with property/tenant details
|
||||||
|
- [ ] Add approval/rejection interface
|
||||||
|
- [ ] Update navigation with approval badge
|
||||||
|
- [ ] Create dedicated `/landlord/approvals` page
|
||||||
|
|
||||||
|
### 7. Testing (LOW PRIORITY)
|
||||||
|
- [ ] Unit tests for lease service functions
|
||||||
|
- [ ] Integration tests for API endpoints
|
||||||
|
- [ ] E2E tests for complete approval workflow
|
||||||
|
- [ ] UI tests for dashboard and invite page
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
After each major component, run:
|
||||||
|
```bash
|
||||||
|
deno check <modified_ts_file>
|
||||||
|
deno fmt <modified_ts_file>
|
||||||
|
deno lint <modified_ts_file>
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: `deno check` only works on TypeScript files (.ts), not Markdown files (.md).
|
||||||
|
|
||||||
|
## Workflow Summary
|
||||||
|
1. Tenant clicks "Start Lease" → Creates lease with `approval_status: 'pending_approval'`
|
||||||
|
2. Landlord receives notification → Dashboard shows pending approval
|
||||||
|
3. Landlord reviews and approves/rejects → Updates lease status
|
||||||
|
4. System finalizes lease → Links records, sets up payments, grants access
|
||||||
|
|
||||||
|
## Files to Modify
|
||||||
|
- `db/schema.ts` - Add approval fields
|
||||||
|
- `services/leaseService.ts` - Add approval functions
|
||||||
|
- `routes/tenant/invite/[invite_id].tsx` - Update UI and logic
|
||||||
|
- `routes/landlord/dashboard/index.tsx` - Add pending approvals
|
||||||
|
- `routes/api/lease/` - Create approval endpoints
|
||||||
|
- `services/notificationService.ts` - New notification service
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
- [ ] All lease activations require landlord approval
|
||||||
|
- [ ] Tenants see clear approval status
|
||||||
|
- [ ] Landlords can easily review and approve/reject
|
||||||
|
- [ ] Notifications are sent reliably
|
||||||
|
- [ ] Lease finalization works correctly
|
||||||
|
- [ ] All tests pass
|
||||||
64
drizzle/0001_spicy_sunset_bain.sql
Normal file
64
drizzle/0001_spicy_sunset_bain.sql
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
CREATE TABLE "reminders" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"lease_id" text,
|
||||||
|
"reminder_type" text NOT NULL,
|
||||||
|
"title" text NOT NULL,
|
||||||
|
"description" text,
|
||||||
|
"due_date" bigint NOT NULL,
|
||||||
|
"is_completed" boolean DEFAULT false,
|
||||||
|
"created_on" bigint,
|
||||||
|
"updated_on" bigint
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "tenant_invites" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"landlord_id" text,
|
||||||
|
"property_id" text,
|
||||||
|
"lease_id" text,
|
||||||
|
"available_on" bigint,
|
||||||
|
"invited_emails" text,
|
||||||
|
"created_on" bigint,
|
||||||
|
"updated_on" bigint
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "web_tokens" (
|
||||||
|
"token_id" varchar(64) PRIMARY KEY NOT NULL,
|
||||||
|
"state_id" varchar(36) NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"token_type" text NOT NULL,
|
||||||
|
"token_value" text NOT NULL,
|
||||||
|
"expires_on" bigint NOT NULL,
|
||||||
|
"created_on" bigint NOT NULL,
|
||||||
|
"updated_on" bigint NOT NULL,
|
||||||
|
"last_used_on" bigint,
|
||||||
|
"is_active" boolean DEFAULT true,
|
||||||
|
"metadata" json
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "brain_question_progress" ADD COLUMN "current_mode" text DEFAULT 'photo-see-bisaya' NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "brain_question_progress" ADD COLUMN "mode_index" integer DEFAULT 0;--> statement-breakpoint
|
||||||
|
ALTER TABLE "brain_question_progress" ADD COLUMN "consecutive_first_try" integer DEFAULT 0;--> statement-breakpoint
|
||||||
|
ALTER TABLE "brain_question_progress" ADD COLUMN "is_review_only" boolean DEFAULT false;--> statement-breakpoint
|
||||||
|
ALTER TABLE "leases" ADD COLUMN "default_payment_method_id" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "messages" ADD COLUMN "parent_message_id" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "messages" ADD COLUMN "attachments_json" json;--> statement-breakpoint
|
||||||
|
ALTER TABLE "properties" ADD COLUMN "default_payment_method_id" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "quiz_configs" ADD COLUMN "tab_name" text;--> statement-breakpoint
|
||||||
|
ALTER TABLE "quiz_configs" ADD COLUMN "tab_index" integer DEFAULT 0;--> statement-breakpoint
|
||||||
|
ALTER TABLE "quiz_configs" ADD COLUMN "list_index" integer DEFAULT 0;--> statement-breakpoint
|
||||||
|
ALTER TABLE "quiz_questions" ADD COLUMN "question_index" integer DEFAULT 0;--> statement-breakpoint
|
||||||
|
ALTER TABLE "tenant_applications" ADD COLUMN "document_urls_json" json;--> statement-breakpoint
|
||||||
|
ALTER TABLE "users" ADD COLUMN "onboarded_landlord" boolean DEFAULT false;--> statement-breakpoint
|
||||||
|
ALTER TABLE "users" ADD COLUMN "onboarded_tenant" boolean DEFAULT false;--> statement-breakpoint
|
||||||
|
ALTER TABLE "users" ADD COLUMN "notification_preferences_json" json;--> statement-breakpoint
|
||||||
|
ALTER TABLE "users" ADD COLUMN "payment_preferences_json" json;--> statement-breakpoint
|
||||||
|
ALTER TABLE "reminders" ADD CONSTRAINT "reminders_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "reminders" ADD CONSTRAINT "reminders_lease_id_leases_id_fk" FOREIGN KEY ("lease_id") REFERENCES "public"."leases"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "tenant_invites" ADD CONSTRAINT "tenant_invites_landlord_id_users_id_fk" FOREIGN KEY ("landlord_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "tenant_invites" ADD CONSTRAINT "tenant_invites_property_id_properties_id_fk" FOREIGN KEY ("property_id") REFERENCES "public"."properties"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "tenant_invites" ADD CONSTRAINT "tenant_invites_lease_id_leases_id_fk" FOREIGN KEY ("lease_id") REFERENCES "public"."leases"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "web_tokens" ADD CONSTRAINT "web_tokens_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "leases" ADD CONSTRAINT "leases_default_payment_method_id_payment_methods_id_fk" FOREIGN KEY ("default_payment_method_id") REFERENCES "public"."payment_methods"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "properties" ADD CONSTRAINT "properties_default_payment_method_id_payment_methods_id_fk" FOREIGN KEY ("default_payment_method_id") REFERENCES "public"."payment_methods"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
ALTER TABLE "brain_question_progress" DROP COLUMN "mode";
|
||||||
8
drizzle/0007_add_lease_id_to_tenant_invites.sql
Normal file
8
drizzle/0007_add_lease_id_to_tenant_invites.sql
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-- Migration: Add lease_id column to tenant_invites table
|
||||||
|
|
||||||
|
ALTER TABLE "tenant_invites" ADD COLUMN "lease_id" text REFERENCES "leases"("id");
|
||||||
|
|
||||||
|
--> statement-breakpoint
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "tenant_invites_lease_id_idx"
|
||||||
|
ON "tenant_invites" ("lease_id");
|
||||||
2578
drizzle/meta/0001_snapshot.json
Normal file
2578
drizzle/meta/0001_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,13 @@
|
|||||||
"when": 1765422865294,
|
"when": 1765422865294,
|
||||||
"tag": "0000_gifted_stepford_cuckoos",
|
"tag": "0000_gifted_stepford_cuckoos",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 1,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1769631945820,
|
||||||
|
"tag": "0001_spicy_sunset_bain",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user