feat: add core database schema and demo seed data for Freelancer OS MVP

This commit is contained in:
Poyraz Avsever
2026-06-01 11:51:43 +03:00
parent 53a225594a
commit c0d25a87e8
8 changed files with 698 additions and 0 deletions
+10
View File
@@ -448,6 +448,16 @@ Kabul kriteri:
- Kullanici sadece kendi verisini gorur. - Kullanici sadece kendi verisini gorur.
- Demo data ile dashboard beslenebilir. - Demo data ile dashboard beslenebilir.
Faz 1 repo ciktisi:
- Core schema migration: `supabase/migrations/0002_add_freelancer_os_core_tables.sql`
- Demo seed dosyasi: `supabase/seeds/0001_demo_freelancer_os_data.sql`
- Migration dokumani: `docs/database/0002-freelancer-os-core-tables.md`
- Seed dokumani: `docs/database/seed-0001-demo-freelancer-os-data.md`
- Query sirasi kaydi: `docs/database/query-order.md`
Not: SQL dosyalari repo icinde hazirdir. Supabase ortaminda calistirildiktan sonra `docs/database/query-log.md` guncellenmelidir.
--- ---
### Faz 2: Core CRUD Modulleri ### Faz 2: Core CRUD Modulleri
@@ -0,0 +1,72 @@
# 0002 Freelancer OS Core Tables
SQL file: `supabase/migrations/0002_add_freelancer_os_core_tables.sql`
## Purpose
Adds the database model required for the Freelancer OS MVP.
This migration keeps the existing baseline from `supabase/schema.sql` and extends it instead of replacing it. The existing `tasks` table is reused and enriched with freelancer-specific fields.
## What It Creates
- `clients`
- `projects`
- `calendar_events`
- `finance_transactions`
- `daily_logs`
- `app_settings`
- `set_updated_at()` trigger function
- updated-at triggers for the new tables
- indexes for common dashboard/report queries
- RLS policies for every new table
## What It Changes
The existing `tasks` table gets these additional columns:
- `client_id`
- `project_id`
- `priority`
- `due_at`
- `estimated_minutes`
- `actual_minutes`
This lets a task belong to a client and/or project while preserving the earlier journal/task prototype schema.
## MVP Coverage
This migration supports:
- client management
- client projects
- side projects
- task planning
- calendar planning
- income and expense tracking
- daily mood/energy logging
- app and AI provider settings
## RLS Model
Every new table has `user_id`.
Policies follow the same pattern:
- users can select their own rows
- users can insert rows only for themselves
- users can update their own rows
- users can delete their own rows
## Notes
`app_settings.api_key` exists for compatibility with the current prototype flow. For production-grade use, provider credentials should be encrypted or moved to a safer secret-management strategy.
`daily_logs` is the new MVP-oriented replacement for the earlier `journals` concept. The old `journals` table remains available until the UI migration is complete.
## Execution
Run this after `supabase/schema.sql`.
Do not add this file to `query-log.md` until it has actually been executed against a database.
+9
View File
@@ -15,7 +15,11 @@ The project currently starts with `supabase/schema.sql` as the first database qu
## Current Files ## Current Files
- `supabase/schema.sql`: Initial legacy schema. It creates the current auth/profile, journal, task, chat, and avatar storage structure. - `supabase/schema.sql`: Initial legacy schema. It creates the current auth/profile, journal, task, chat, and avatar storage structure.
- `supabase/migrations/0002_add_freelancer_os_core_tables.sql`: Freelancer OS MVP core schema.
- `supabase/seeds/0001_demo_freelancer_os_data.sql`: Optional local/demo data for the MVP schema.
- `docs/database/0001-initial-schema.md`: Explanation for the initial schema. - `docs/database/0001-initial-schema.md`: Explanation for the initial schema.
- `docs/database/0002-freelancer-os-core-tables.md`: Explanation for the MVP schema migration.
- `docs/database/seed-0001-demo-freelancer-os-data.md`: Explanation for the demo seed file.
- `docs/database/query-order.md`: Canonical order of SQL files. - `docs/database/query-order.md`: Canonical order of SQL files.
- `docs/database/query-log.md`: Manual execution log for SQL files that were run against an environment. - `docs/database/query-log.md`: Manual execution log for SQL files that were run against an environment.
@@ -33,3 +37,8 @@ Example:
supabase/migrations/0002_add_freelancer_os_core_tables.sql supabase/migrations/0002_add_freelancer_os_core_tables.sql
``` ```
Use this pattern for future seed files:
```text
supabase/seeds/0002_short_description.sql
```
+7
View File
@@ -5,6 +5,8 @@ This file is the canonical order of SQL files for database setup and migration.
| Order | SQL file | Documentation | Status | | Order | SQL file | Documentation | Status |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| 0001 | `supabase/schema.sql` | `docs/database/0001-initial-schema.md` | Baseline registered | | 0001 | `supabase/schema.sql` | `docs/database/0001-initial-schema.md` | Baseline registered |
| 0002 | `supabase/migrations/0002_add_freelancer_os_core_tables.sql` | `docs/database/0002-freelancer-os-core-tables.md` | Pending execution |
| seed-0001 | `supabase/seeds/0001_demo_freelancer_os_data.sql` | `docs/database/seed-0001-demo-freelancer-os-data.md` | Optional demo seed, pending execution |
## How To Add The Next Query ## How To Add The Next Query
@@ -14,3 +16,8 @@ This file is the canonical order of SQL files for database setup and migration.
4. Register both files in this table. 4. Register both files in this table.
5. After running the SQL, add an entry to `query-log.md`. 5. After running the SQL, add an entry to `query-log.md`.
## Seed Files
Seed files are optional and should live under `supabase/seeds/`.
They must also be documented and registered in this file, but they should only be run in local/demo environments unless explicitly approved.
@@ -0,0 +1,43 @@
# Seed 0001 Demo Freelancer OS Data
SQL file: `supabase/seeds/0001_demo_freelancer_os_data.sql`
## Purpose
Adds demo data for local development and dashboard testing after the Freelancer OS core tables are created.
## What It Inserts
- demo clients
- demo projects and one side project
- demo tasks
- demo calendar events
- demo finance transactions
- demo daily mood/energy logs
- demo `app_settings`
## Required Manual Step
Before running the file, replace this placeholder with a real `auth.users.id`:
```sql
'00000000-0000-0000-0000-000000000000'::uuid
```
Use a user id from your Supabase Auth users table.
## Environment
This seed is intended for local and demo environments only.
Do not run it on production data.
## Execution
Run after:
1. `supabase/schema.sql`
2. `supabase/migrations/0002_add_freelancer_os_core_tables.sql`
After running it, add an entry to `docs/database/query-log.md`.
+11
View File
@@ -17,5 +17,16 @@ Future schema changes should be added under:
supabase/migrations/ supabase/migrations/
``` ```
Optional local/demo data should be added under:
```text
supabase/seeds/
```
Do not overwrite already executed SQL without also creating a new ordered migration and documenting why. Do not overwrite already executed SQL without also creating a new ordered migration and documenting why.
## Current Ordered SQL
1. `schema.sql`
2. `migrations/0002_add_freelancer_os_core_tables.sql`
3. Optional: `seeds/0001_demo_freelancer_os_data.sql`
@@ -0,0 +1,336 @@
-- 0002: Add Freelancer OS core tables
-- Run after: supabase/schema.sql
create extension if not exists "uuid-ossp";
create or replace function public.set_updated_at()
returns trigger as $$
begin
new.updated_at = timezone('utc'::text, now());
return new;
end;
$$ language plpgsql;
create table if not exists public.clients (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id) on delete cascade not null,
name text not null,
company_name text,
email text,
phone text,
website text,
status text default 'active'::text not null,
notes text,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
updated_at timestamp with time zone default timezone('utc'::text, now()) not null
);
create table if not exists public.projects (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id) on delete cascade not null,
client_id uuid references public.clients(id) on delete set null,
name text not null,
type text default 'client_project'::text not null,
description text,
status text default 'planning'::text not null,
start_date date,
due_date date,
budget_amount numeric(12, 2),
currency text default 'USD'::text not null,
progress integer default 0 not null,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
updated_at timestamp with time zone default timezone('utc'::text, now()) not null
);
create table if not exists public.calendar_events (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id) on delete cascade not null,
client_id uuid references public.clients(id) on delete set null,
project_id uuid references public.projects(id) on delete set null,
task_id uuid references public.tasks(id) on delete set null,
title text not null,
description text,
type text default 'focus'::text not null,
starts_at timestamp with time zone not null,
ends_at timestamp with time zone,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
updated_at timestamp with time zone default timezone('utc'::text, now()) not null
);
create table if not exists public.finance_transactions (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id) on delete cascade not null,
client_id uuid references public.clients(id) on delete set null,
project_id uuid references public.projects(id) on delete set null,
type text not null,
amount numeric(12, 2) not null,
currency text default 'USD'::text not null,
transaction_date date default current_date not null,
category text,
payment_status text default 'planned'::text not null,
description text,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
updated_at timestamp with time zone default timezone('utc'::text, now()) not null
);
create table if not exists public.daily_logs (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id) on delete cascade not null,
log_date date default current_date not null,
mood_score smallint not null,
energy_score smallint not null,
work_satisfaction_score smallint,
note text,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
updated_at timestamp with time zone default timezone('utc'::text, now()) not null,
unique (user_id, log_date)
);
create table if not exists public.app_settings (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users(id) on delete cascade not null unique,
timezone text default 'UTC'::text not null,
currency text default 'USD'::text not null,
ai_provider text default 'ollama'::text not null,
ai_model text,
api_key text,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
updated_at timestamp with time zone default timezone('utc'::text, now()) not null
);
alter table public.tasks
add column if not exists client_id uuid references public.clients(id) on delete set null,
add column if not exists project_id uuid references public.projects(id) on delete set null,
add column if not exists priority text default 'medium'::text not null,
add column if not exists due_at timestamp with time zone,
add column if not exists estimated_minutes integer,
add column if not exists actual_minutes integer;
do $$
begin
if not exists (select 1 from pg_constraint where conname = 'clients_status_check') then
alter table public.clients
add constraint clients_status_check
check (status in ('active', 'paused', 'archived'));
end if;
if not exists (select 1 from pg_constraint where conname = 'projects_type_check') then
alter table public.projects
add constraint projects_type_check
check (type in ('client_project', 'side_project'));
end if;
if not exists (select 1 from pg_constraint where conname = 'projects_status_check') then
alter table public.projects
add constraint projects_status_check
check (status in ('planning', 'active', 'paused', 'completed', 'cancelled'));
end if;
if not exists (select 1 from pg_constraint where conname = 'projects_progress_check') then
alter table public.projects
add constraint projects_progress_check
check (progress >= 0 and progress <= 100);
end if;
if not exists (select 1 from pg_constraint where conname = 'tasks_priority_check') then
alter table public.tasks
add constraint tasks_priority_check
check (priority in ('low', 'medium', 'high', 'urgent'));
end if;
if not exists (select 1 from pg_constraint where conname = 'calendar_events_type_check') then
alter table public.calendar_events
add constraint calendar_events_type_check
check (type in ('meeting', 'focus', 'deadline', 'personal', 'finance'));
end if;
if not exists (select 1 from pg_constraint where conname = 'calendar_events_time_check') then
alter table public.calendar_events
add constraint calendar_events_time_check
check (ends_at is null or ends_at >= starts_at);
end if;
if not exists (select 1 from pg_constraint where conname = 'finance_transactions_type_check') then
alter table public.finance_transactions
add constraint finance_transactions_type_check
check (type in ('income', 'expense'));
end if;
if not exists (select 1 from pg_constraint where conname = 'finance_transactions_amount_check') then
alter table public.finance_transactions
add constraint finance_transactions_amount_check
check (amount >= 0);
end if;
if not exists (select 1 from pg_constraint where conname = 'finance_transactions_payment_status_check') then
alter table public.finance_transactions
add constraint finance_transactions_payment_status_check
check (payment_status in ('planned', 'pending', 'paid', 'cancelled'));
end if;
if not exists (select 1 from pg_constraint where conname = 'daily_logs_mood_score_check') then
alter table public.daily_logs
add constraint daily_logs_mood_score_check
check (mood_score between 1 and 5);
end if;
if not exists (select 1 from pg_constraint where conname = 'daily_logs_energy_score_check') then
alter table public.daily_logs
add constraint daily_logs_energy_score_check
check (energy_score between 1 and 5);
end if;
if not exists (select 1 from pg_constraint where conname = 'daily_logs_work_satisfaction_score_check') then
alter table public.daily_logs
add constraint daily_logs_work_satisfaction_score_check
check (work_satisfaction_score is null or work_satisfaction_score between 1 and 5);
end if;
if not exists (select 1 from pg_constraint where conname = 'app_settings_ai_provider_check') then
alter table public.app_settings
add constraint app_settings_ai_provider_check
check (ai_provider in ('ollama', 'openai', 'gemini', 'groq'));
end if;
end $$;
create index if not exists clients_user_id_idx on public.clients(user_id);
create index if not exists clients_status_idx on public.clients(status);
create index if not exists projects_user_id_idx on public.projects(user_id);
create index if not exists projects_client_id_idx on public.projects(client_id);
create index if not exists projects_status_idx on public.projects(status);
create index if not exists projects_due_date_idx on public.projects(due_date);
create index if not exists tasks_client_id_idx on public.tasks(client_id);
create index if not exists tasks_project_id_idx on public.tasks(project_id);
create index if not exists tasks_due_at_idx on public.tasks(due_at);
create index if not exists tasks_priority_idx on public.tasks(priority);
create index if not exists calendar_events_user_id_idx on public.calendar_events(user_id);
create index if not exists calendar_events_starts_at_idx on public.calendar_events(starts_at);
create index if not exists calendar_events_project_id_idx on public.calendar_events(project_id);
create index if not exists calendar_events_task_id_idx on public.calendar_events(task_id);
create index if not exists finance_transactions_user_id_idx on public.finance_transactions(user_id);
create index if not exists finance_transactions_client_id_idx on public.finance_transactions(client_id);
create index if not exists finance_transactions_project_id_idx on public.finance_transactions(project_id);
create index if not exists finance_transactions_transaction_date_idx on public.finance_transactions(transaction_date);
create index if not exists finance_transactions_payment_status_idx on public.finance_transactions(payment_status);
create index if not exists daily_logs_user_id_idx on public.daily_logs(user_id);
create index if not exists daily_logs_log_date_idx on public.daily_logs(log_date);
alter table public.clients enable row level security;
alter table public.projects enable row level security;
alter table public.calendar_events enable row level security;
alter table public.finance_transactions enable row level security;
alter table public.daily_logs enable row level security;
alter table public.app_settings enable row level security;
drop policy if exists "Users can view their own clients." on public.clients;
create policy "Users can view their own clients." on public.clients
for select using (auth.uid() = user_id);
drop policy if exists "Users can insert their own clients." on public.clients;
create policy "Users can insert their own clients." on public.clients
for insert with check (auth.uid() = user_id);
drop policy if exists "Users can update their own clients." on public.clients;
create policy "Users can update their own clients." on public.clients
for update using (auth.uid() = user_id);
drop policy if exists "Users can delete their own clients." on public.clients;
create policy "Users can delete their own clients." on public.clients
for delete using (auth.uid() = user_id);
drop policy if exists "Users can view their own projects." on public.projects;
create policy "Users can view their own projects." on public.projects
for select using (auth.uid() = user_id);
drop policy if exists "Users can insert their own projects." on public.projects;
create policy "Users can insert their own projects." on public.projects
for insert with check (auth.uid() = user_id);
drop policy if exists "Users can update their own projects." on public.projects;
create policy "Users can update their own projects." on public.projects
for update using (auth.uid() = user_id);
drop policy if exists "Users can delete their own projects." on public.projects;
create policy "Users can delete their own projects." on public.projects
for delete using (auth.uid() = user_id);
drop policy if exists "Users can view their own calendar events." on public.calendar_events;
create policy "Users can view their own calendar events." on public.calendar_events
for select using (auth.uid() = user_id);
drop policy if exists "Users can insert their own calendar events." on public.calendar_events;
create policy "Users can insert their own calendar events." on public.calendar_events
for insert with check (auth.uid() = user_id);
drop policy if exists "Users can update their own calendar events." on public.calendar_events;
create policy "Users can update their own calendar events." on public.calendar_events
for update using (auth.uid() = user_id);
drop policy if exists "Users can delete their own calendar events." on public.calendar_events;
create policy "Users can delete their own calendar events." on public.calendar_events
for delete using (auth.uid() = user_id);
drop policy if exists "Users can view their own finance transactions." on public.finance_transactions;
create policy "Users can view their own finance transactions." on public.finance_transactions
for select using (auth.uid() = user_id);
drop policy if exists "Users can insert their own finance transactions." on public.finance_transactions;
create policy "Users can insert their own finance transactions." on public.finance_transactions
for insert with check (auth.uid() = user_id);
drop policy if exists "Users can update their own finance transactions." on public.finance_transactions;
create policy "Users can update their own finance transactions." on public.finance_transactions
for update using (auth.uid() = user_id);
drop policy if exists "Users can delete their own finance transactions." on public.finance_transactions;
create policy "Users can delete their own finance transactions." on public.finance_transactions
for delete using (auth.uid() = user_id);
drop policy if exists "Users can view their own daily logs." on public.daily_logs;
create policy "Users can view their own daily logs." on public.daily_logs
for select using (auth.uid() = user_id);
drop policy if exists "Users can insert their own daily logs." on public.daily_logs;
create policy "Users can insert their own daily logs." on public.daily_logs
for insert with check (auth.uid() = user_id);
drop policy if exists "Users can update their own daily logs." on public.daily_logs;
create policy "Users can update their own daily logs." on public.daily_logs
for update using (auth.uid() = user_id);
drop policy if exists "Users can delete their own daily logs." on public.daily_logs;
create policy "Users can delete their own daily logs." on public.daily_logs
for delete using (auth.uid() = user_id);
drop policy if exists "Users can view their own app settings." on public.app_settings;
create policy "Users can view their own app settings." on public.app_settings
for select using (auth.uid() = user_id);
drop policy if exists "Users can insert their own app settings." on public.app_settings;
create policy "Users can insert their own app settings." on public.app_settings
for insert with check (auth.uid() = user_id);
drop policy if exists "Users can update their own app settings." on public.app_settings;
create policy "Users can update their own app settings." on public.app_settings
for update using (auth.uid() = user_id);
drop policy if exists "Users can delete their own app settings." on public.app_settings;
create policy "Users can delete their own app settings." on public.app_settings
for delete using (auth.uid() = user_id);
drop trigger if exists set_clients_updated_at on public.clients;
create trigger set_clients_updated_at
before update on public.clients
for each row execute procedure public.set_updated_at();
drop trigger if exists set_projects_updated_at on public.projects;
create trigger set_projects_updated_at
before update on public.projects
for each row execute procedure public.set_updated_at();
drop trigger if exists set_calendar_events_updated_at on public.calendar_events;
create trigger set_calendar_events_updated_at
before update on public.calendar_events
for each row execute procedure public.set_updated_at();
drop trigger if exists set_finance_transactions_updated_at on public.finance_transactions;
create trigger set_finance_transactions_updated_at
before update on public.finance_transactions
for each row execute procedure public.set_updated_at();
drop trigger if exists set_daily_logs_updated_at on public.daily_logs;
create trigger set_daily_logs_updated_at
before update on public.daily_logs
for each row execute procedure public.set_updated_at();
drop trigger if exists set_app_settings_updated_at on public.app_settings;
create trigger set_app_settings_updated_at
before update on public.app_settings
for each row execute procedure public.set_updated_at();
@@ -0,0 +1,210 @@
-- Seed 0001: Demo Freelancer OS data
-- Run after: supabase/migrations/0002_add_freelancer_os_core_tables.sql
--
-- Before running, replace the UUID below with an existing auth.users.id.
-- This file is for local/demo environments. Do not run it on production data.
with seed_user as (
select '00000000-0000-0000-0000-000000000000'::uuid as user_id
),
demo_clients as (
insert into public.clients (user_id, name, company_name, email, status, notes)
select user_id, 'Acme Studio', 'Acme Studio LLC', 'hello@acme.example', 'active', 'Primary design and web retainer client.'
from seed_user
union all
select user_id, 'Northwind Labs', 'Northwind Labs', 'ops@northwind.example', 'active', 'Product strategy project with monthly milestones.'
from seed_user
returning id, user_id, name
),
demo_projects as (
insert into public.projects (user_id, client_id, name, type, description, status, start_date, due_date, budget_amount, currency, progress)
select
c.user_id,
c.id,
'Acme Website Refresh',
'client_project',
'Marketing website refresh and conversion improvements.',
'active',
current_date - 14,
current_date + 21,
4200,
'USD',
45
from demo_clients c
where c.name = 'Acme Studio'
union all
select
c.user_id,
c.id,
'Northwind Product Audit',
'client_project',
'Audit onboarding, analytics, and project roadmap.',
'active',
current_date - 7,
current_date + 14,
2800,
'USD',
30
from demo_clients c
where c.name = 'Northwind Labs'
union all
select
user_id,
null,
'Cognis Open Source Launch',
'side_project',
'Prepare the self-hosted Freelancer OS MVP for public release.',
'planning',
current_date,
current_date + 45,
null,
'USD',
10
from seed_user
returning id, user_id, client_id, name
),
demo_tasks as (
insert into public.tasks (user_id, client_id, project_id, title, description, status, priority, due_at, estimated_minutes, actual_minutes)
select
p.user_id,
p.client_id,
p.id,
'Prepare homepage wireframe',
'Create first-pass homepage structure for client review.',
'todo',
'high',
timezone('utc'::text, now()) + interval '2 days',
180,
null
from demo_projects p
where p.name = 'Acme Website Refresh'
union all
select
p.user_id,
p.client_id,
p.id,
'Review onboarding analytics',
'Summarize funnel drop-off points and quick wins.',
'in_progress',
'urgent',
timezone('utc'::text, now()) + interval '1 day',
120,
45
from demo_projects p
where p.name = 'Northwind Product Audit'
union all
select
p.user_id,
p.client_id,
p.id,
'Write MVP installation notes',
'Document self-host setup, env vars, and migration order.',
'todo',
'medium',
timezone('utc'::text, now()) + interval '5 days',
90,
null
from demo_projects p
where p.name = 'Cognis Open Source Launch'
returning id, user_id, client_id, project_id, title
),
demo_events as (
insert into public.calendar_events (user_id, client_id, project_id, task_id, title, description, type, starts_at, ends_at)
select
t.user_id,
t.client_id,
t.project_id,
t.id,
'Client review: homepage wireframe',
'Review initial direction with Acme.',
'meeting',
timezone('utc'::text, now()) + interval '3 days',
timezone('utc'::text, now()) + interval '3 days 1 hour'
from demo_tasks t
where t.title = 'Prepare homepage wireframe'
union all
select
t.user_id,
t.client_id,
t.project_id,
t.id,
'Deep work: analytics audit',
'Focus block for Northwind analysis.',
'focus',
timezone('utc'::text, now()) + interval '1 day',
timezone('utc'::text, now()) + interval '1 day 2 hours'
from demo_tasks t
where t.title = 'Review onboarding analytics'
returning id
),
demo_finance as (
insert into public.finance_transactions (user_id, client_id, project_id, type, amount, currency, transaction_date, category, payment_status, description)
select
p.user_id,
p.client_id,
p.id,
'income',
2100,
'USD',
current_date - 3,
'Project deposit',
'paid',
'Acme Website Refresh initial payment.'
from demo_projects p
where p.name = 'Acme Website Refresh'
union all
select
p.user_id,
p.client_id,
p.id,
'income',
2800,
'USD',
current_date + 10,
'Project payment',
'pending',
'Northwind audit payment due.'
from demo_projects p
where p.name = 'Northwind Product Audit'
union all
select
user_id,
null,
null,
'expense',
49,
'USD',
current_date,
'Software',
'paid',
'Monthly tool subscription.'
from seed_user
returning id
),
demo_daily_logs as (
insert into public.daily_logs (user_id, log_date, mood_score, energy_score, work_satisfaction_score, note)
select user_id, current_date - 2, 3, 3, 3, 'Mixed admin day with some client context switching.'
from seed_user
union all
select user_id, current_date - 1, 4, 5, 4, 'Strong focus block and clear project progress.'
from seed_user
union all
select user_id, current_date, 4, 4, 4, 'Good planning momentum for the week.'
from seed_user
on conflict (user_id, log_date) do update set
mood_score = excluded.mood_score,
energy_score = excluded.energy_score,
work_satisfaction_score = excluded.work_satisfaction_score,
note = excluded.note,
updated_at = timezone('utc'::text, now())
returning id
)
insert into public.app_settings (user_id, timezone, currency, ai_provider, ai_model)
select user_id, 'UTC', 'USD', 'ollama', 'llama3'
from seed_user
on conflict (user_id) do update set
timezone = excluded.timezone,
currency = excluded.currency,
ai_provider = excluded.ai_provider,
ai_model = excluded.ai_model,
updated_at = timezone('utc'::text, now());