feat(tools): add maintenance and meal planning tools with CRUD operations
- Implement maintenance tool for adding, logging, and retrieving tasks - Create meals tool for managing recipes, meal plans, and shopping lists - Introduce reparse metadata tool for updating thought metadata - Add household knowledge, home maintenance, family calendar, meal planning, and professional CRM database migrations - Grant necessary permissions for new database tables
This commit is contained in:
71
migrations/015_professional_crm.sql
Normal file
71
migrations/015_professional_crm.sql
Normal file
@@ -0,0 +1,71 @@
|
||||
-- Extension 5: Professional CRM
|
||||
-- Contacts, interaction logs, and opportunities (single-user, no RLS)
|
||||
|
||||
CREATE TABLE IF NOT EXISTS professional_contacts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
company TEXT,
|
||||
title TEXT,
|
||||
email TEXT,
|
||||
phone TEXT,
|
||||
linkedin_url TEXT,
|
||||
how_we_met TEXT,
|
||||
tags TEXT[] NOT NULL DEFAULT '{}',
|
||||
notes TEXT,
|
||||
last_contacted TIMESTAMPTZ,
|
||||
follow_up_date DATE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS contact_interactions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
contact_id UUID NOT NULL REFERENCES professional_contacts(id) ON DELETE CASCADE,
|
||||
interaction_type TEXT NOT NULL CHECK (interaction_type IN ('meeting', 'email', 'call', 'coffee', 'event', 'linkedin', 'other')),
|
||||
occurred_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
summary TEXT NOT NULL,
|
||||
follow_up_needed BOOLEAN NOT NULL DEFAULT false,
|
||||
follow_up_notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS opportunities (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
contact_id UUID REFERENCES professional_contacts(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
stage TEXT NOT NULL DEFAULT 'identified' CHECK (stage IN ('identified', 'in_conversation', 'proposal', 'negotiation', 'won', 'lost')),
|
||||
value DECIMAL(12, 2),
|
||||
expected_close_date DATE,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_contacts_last_contacted ON professional_contacts(last_contacted);
|
||||
CREATE INDEX IF NOT EXISTS idx_contacts_follow_up ON professional_contacts(follow_up_date) WHERE follow_up_date IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_interactions_contact ON contact_interactions(contact_id, occurred_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_opportunities_stage ON opportunities(stage);
|
||||
|
||||
DROP TRIGGER IF EXISTS update_professional_contacts_updated_at ON professional_contacts;
|
||||
CREATE TRIGGER update_professional_contacts_updated_at
|
||||
BEFORE UPDATE ON professional_contacts
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
DROP TRIGGER IF EXISTS update_opportunities_updated_at ON opportunities;
|
||||
CREATE TRIGGER update_opportunities_updated_at
|
||||
BEFORE UPDATE ON opportunities
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_last_contacted()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
UPDATE professional_contacts SET last_contacted = NEW.occurred_at WHERE id = NEW.contact_id;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS update_contact_last_contacted ON contact_interactions;
|
||||
CREATE TRIGGER update_contact_last_contacted
|
||||
AFTER INSERT ON contact_interactions
|
||||
FOR EACH ROW EXECUTE FUNCTION update_last_contacted();
|
||||
Reference in New Issue
Block a user