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:
2026-03-26 23:29:03 +02:00
parent b74d63c543
commit 0eb6ac7ee5
25 changed files with 2910 additions and 10 deletions

View 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();