Frist commit

This commit is contained in:
2026-07-19 23:04:16 +09:00
commit f093d41f60
33 changed files with 4077 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
"""Centralized SQL for mail_summary."""
class Schema:
ENSURE_ANALYSIS_JOBS = """
CREATE TABLE IF NOT EXISTS analysis_jobs (
id BIGSERIAL PRIMARY KEY,
status TEXT NOT NULL DEFAULT 'pending',
mailbox_scope TEXT NOT NULL DEFAULT 'both',
date_from DATE NOT NULL,
date_to DATE NOT NULL,
model TEXT NOT NULL DEFAULT '',
inbox_zip_name TEXT,
sent_zip_name TEXT,
inbox_count INTEGER NOT NULL DEFAULT 0,
sent_count INTEGER NOT NULL DEFAULT 0,
filtered_inbox_count INTEGER NOT NULL DEFAULT 0,
filtered_sent_count INTEGER NOT NULL DEFAULT 0,
progress_pct INTEGER NOT NULL DEFAULT 0,
progress_label TEXT NOT NULL DEFAULT '',
progress_detail TEXT NOT NULL DEFAULT '',
error_message TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
CONSTRAINT analysis_jobs_status_chk CHECK (
status IN ('pending', 'extracting', 'filtering', 'analyzing', 'completed', 'failed')
),
CONSTRAINT analysis_jobs_scope_chk CHECK (
mailbox_scope IN ('inbox', 'sent', 'both')
),
CONSTRAINT analysis_jobs_date_chk CHECK (date_from <= date_to)
)
"""
ADD_PROGRESS_PCT = """
ALTER TABLE analysis_jobs
ADD COLUMN IF NOT EXISTS progress_pct INTEGER NOT NULL DEFAULT 0
"""
ADD_PROGRESS_LABEL = """
ALTER TABLE analysis_jobs
ADD COLUMN IF NOT EXISTS progress_label TEXT NOT NULL DEFAULT ''
"""
ADD_PROGRESS_DETAIL = """
ALTER TABLE analysis_jobs
ADD COLUMN IF NOT EXISTS progress_detail TEXT NOT NULL DEFAULT ''
"""
IDX_ANALYSIS_JOBS_CREATED_AT = """
CREATE INDEX IF NOT EXISTS idx_analysis_jobs_created_at
ON analysis_jobs (created_at DESC)
"""
IDX_ANALYSIS_JOBS_STATUS = """
CREATE INDEX IF NOT EXISTS idx_analysis_jobs_status
ON analysis_jobs (status)
"""
ENSURE_MAILS = """
CREATE TABLE IF NOT EXISTS mails (
id BIGSERIAL PRIMARY KEY,
job_id BIGINT NOT NULL REFERENCES analysis_jobs(id) ON DELETE CASCADE,
mailbox TEXT NOT NULL,
message_id TEXT,
thread_key TEXT,
subject TEXT NOT NULL DEFAULT '',
from_addr TEXT NOT NULL DEFAULT '',
to_addrs TEXT NOT NULL DEFAULT '',
cc_addrs TEXT NOT NULL DEFAULT '',
mailed_at TIMESTAMPTZ,
attachment_names JSONB NOT NULL DEFAULT '[]'::jsonb,
body_text TEXT,
body_purged BOOLEAN NOT NULL DEFAULT FALSE,
summary JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT mails_mailbox_chk CHECK (mailbox IN ('inbox', 'sent'))
)
"""
IDX_MAILS_JOB_ID = "CREATE INDEX IF NOT EXISTS idx_mails_job_id ON mails (job_id)"
IDX_MAILS_JOB_MAILED_AT = (
"CREATE INDEX IF NOT EXISTS idx_mails_job_mailed_at ON mails (job_id, mailed_at)"
)
IDX_MAILS_THREAD_KEY = (
"CREATE INDEX IF NOT EXISTS idx_mails_thread_key ON mails (job_id, thread_key)"
)
IDX_MAILS_MESSAGE_ID = (
"CREATE INDEX IF NOT EXISTS idx_mails_message_id ON mails (job_id, message_id)"
)
ENSURE_WEEKLY_REPORTS = """
CREATE TABLE IF NOT EXISTS weekly_reports (
id BIGSERIAL PRIMARY KEY,
job_id BIGINT NOT NULL UNIQUE REFERENCES analysis_jobs(id) ON DELETE CASCADE,
model TEXT NOT NULL DEFAULT '',
scope_note TEXT NOT NULL DEFAULT '',
report JSONB NOT NULL DEFAULT '{}'::jsonb,
report_markdown TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
"""
IDX_WEEKLY_REPORTS_CREATED_AT = """
CREATE INDEX IF NOT EXISTS idx_weekly_reports_created_at
ON weekly_reports (created_at DESC)
"""
class Jobs:
INSERT = """
INSERT INTO analysis_jobs (
status, mailbox_scope, date_from, date_to, model,
inbox_zip_name, sent_zip_name
)
VALUES (
'pending', %(mailbox_scope)s, %(date_from)s, %(date_to)s, %(model)s,
%(inbox_zip_name)s, %(sent_zip_name)s
)
RETURNING id, status, mailbox_scope, date_from, date_to, model,
inbox_zip_name, sent_zip_name,
inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
progress_pct, progress_label, progress_detail,
error_message, created_at, started_at, completed_at
"""
GET_BY_ID = """
SELECT id, status, mailbox_scope, date_from, date_to, model,
inbox_zip_name, sent_zip_name,
inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
progress_pct, progress_label, progress_detail,
error_message, created_at, started_at, completed_at
FROM analysis_jobs
WHERE id = %(job_id)s
"""
LIST_RECENT = """
SELECT id, status, mailbox_scope, date_from, date_to, model,
inbox_zip_name, sent_zip_name,
inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
progress_pct, progress_label, progress_detail,
error_message, created_at, started_at, completed_at
FROM analysis_jobs
ORDER BY created_at DESC
LIMIT %(limit)s
"""
UPDATE = """
UPDATE analysis_jobs
SET
status = COALESCE(%(status)s, status),
inbox_count = COALESCE(%(inbox_count)s, inbox_count),
sent_count = COALESCE(%(sent_count)s, sent_count),
filtered_inbox_count = COALESCE(%(filtered_inbox_count)s, filtered_inbox_count),
filtered_sent_count = COALESCE(%(filtered_sent_count)s, filtered_sent_count),
progress_pct = COALESCE(%(progress_pct)s, progress_pct),
progress_label = COALESCE(%(progress_label)s, progress_label),
progress_detail = COALESCE(%(progress_detail)s, progress_detail),
error_message = COALESCE(%(error_message)s, error_message),
started_at = CASE
WHEN %(set_started)s THEN COALESCE(started_at, NOW())
ELSE started_at
END,
completed_at = CASE
WHEN %(set_completed)s THEN NOW()
ELSE completed_at
END
WHERE id = %(job_id)s
RETURNING id, status, mailbox_scope, date_from, date_to, model,
inbox_zip_name, sent_zip_name,
inbox_count, sent_count, filtered_inbox_count, filtered_sent_count,
progress_pct, progress_label, progress_detail,
error_message, created_at, started_at, completed_at
"""
class Mails:
INSERT = """
INSERT INTO mails (
job_id, mailbox, message_id, thread_key, subject,
from_addr, to_addrs, cc_addrs, mailed_at,
attachment_names, body_text
)
VALUES (
%(job_id)s, %(mailbox)s, %(message_id)s, %(thread_key)s, %(subject)s,
%(from_addr)s, %(to_addrs)s, %(cc_addrs)s, %(mailed_at)s,
%(attachment_names)s, %(body_text)s
)
RETURNING id
"""
LIST_BY_JOB = """
SELECT id, job_id, mailbox, message_id, thread_key, subject,
from_addr, to_addrs, cc_addrs, mailed_at,
attachment_names, body_text, body_purged, summary, created_at
FROM mails
WHERE job_id = %(job_id)s
ORDER BY mailed_at NULLS LAST, id
"""
UPDATE_SUMMARY = """
UPDATE mails
SET summary = %(summary)s
WHERE id = %(mail_id)s
"""
PURGE_BODIES = """
UPDATE mails
SET body_text = NULL, body_purged = TRUE
WHERE job_id = %(job_id)s
"""
class Reports:
GET_BY_JOB = """
SELECT id, job_id, model, scope_note, report, report_markdown,
created_at, updated_at
FROM weekly_reports
WHERE job_id = %(job_id)s
"""
UPSERT = """
INSERT INTO weekly_reports (job_id, model, scope_note, report, report_markdown)
VALUES (
%(job_id)s, %(model)s, %(scope_note)s,
%(report)s, %(report_markdown)s
)
ON CONFLICT (job_id) DO UPDATE SET
model = EXCLUDED.model,
scope_note = EXCLUDED.scope_note,
report = EXCLUDED.report,
report_markdown = EXCLUDED.report_markdown,
updated_at = NOW()
RETURNING id, job_id, model, scope_note, report, report_markdown,
created_at, updated_at
"""