# ITSulu Blog Publisher — Odoo 14 Addon **Version:** 0.5.1 Automated blog post generation and publishing for Odoo 14.0 Community Edition, powered by generative AI (Anthropic Claude, OpenAI, Google Gemini, or Ollama). > ⚠️ **Porting in progress.** This `14.0` branch is the target for the ITSulu production > instance. It is seeded from the 17.0 baseline; the Odoo-14 API port (notably the older > Jinja-style mail templates) is tracked in [PORTING.md](PORTING.md). > **Versioning** — `MAJOR.MINOR.PATCH` (each 0–999). MAJOR = major release for sale / significant change; MINOR = features or performance improvements; PATCH = a single group of commits. See [CHANGELOG.md](CHANGELOG.md) for release notes and [CLAUDE.md](CLAUDE.md) §15 for the full scheme. > **Odoo version branches** — like [odoo/odoo](https://github.com/odoo/odoo), each Odoo > Community release lives on its own branch. Supported targets: > **[`19.0`](../../tree/19.0)** (latest stable) and **[`14.0`](../../tree/14.0)** (the version > ITSulu runs). Check out the branch matching your Odoo version. Release tags are namespaced by > series, e.g. `19.0-v0.5.0`. ## Features ### ✨ Core Functionality - **On-Demand Generation** — Wizard-driven blog post creation via backend form - **Scheduled Generation** — Three configurable daily cron slots (morning, afternoon, evening) - **Multi-Provider LLM** — Route requests to Anthropic Claude, OpenAI ChatGPT, Google Gemini, or local Ollama models - **SEO Automation** — Auto-populate meta titles, descriptions, keywords, and tags - **Social Media Copy** — Generate platform-specific posts for X, BlueSky, Mastodon, and LinkedIn - **Auto-Publish** — Publish generated posts immediately or save as drafts for review - **Topic Queue** — Priority-based topic queue for scheduled generation - **Notification Emails** — Automated emails with generated content and social copy - **Generation Audit Trail** — Complete logs with token usage, provider, model, and error tracking - **Error Recovery** — Retry button on failed generation logs ### 🧠 Supported LLM Providers | Provider | Model Examples | Config Parameter | |----------|---|---| | **Anthropic Claude** | claude-sonnet-4-20250514, claude-opus-4-1 | `itsulu_blog_publisher.anthropic_api_key` | | **OpenAI** | gpt-4o, gpt-4-turbo | `itsulu_blog_publisher.openai_api_key` | | **Google Gemini** | gemini-2.0-flash, gemini-pro | `itsulu_blog_publisher.gemini_api_key` | | **Ollama** | Any local model (mistral, llama2, etc.) | `itsulu_blog_publisher.ollama_base_url` | ### 📊 Test Coverage **69 automated tests**, all passing on the ITSulu Kubernetes test cluster. | Test Suite | Count | Status | |---|---|---| | Unit Tests (TDD) | 48 | ✅ All Passing | | Behaviour Tests (BDD) | 15 | ✅ All Passing | | Performance Benchmarks | 6 | ✅ All Passing | | **Total** | **69** | **100% ✅** | **Coverage Areas**: - Topic queue management (7 tests) - Generation audit logs (8 tests) - Social media copy (16 tests) - Schedule slots (10 tests) - LLM router dispatch (7 tests) - E2E / behaviour workflows (15 BDD scenarios) - Performance SLOs — latency, query count, token usage, concurrency (6 benchmarks) Tests run as ephemeral Kubernetes jobs in the `itsulu-testing` namespace against a primed PostgreSQL template database. See [CLAUDE.md](CLAUDE.md) §8 for the K8s test setup. ## Installation ### Prerequisites - Odoo 14.0 Community - Python 3.6–3.8 - PostgreSQL 10+ - pip packages: `requests`, `pytest-odoo`, `pytest-bdd` ### Steps 1. **Clone the repository** into your Odoo addons directory: ```bash git clone https://github.com/itsulu-odoo/itsulu-blog-publisher.git \ /path/to/odoo/addons/itsulu_blog_publisher ``` 2. **Install Python dependencies**: ```bash pip install requests ``` 3. **Install the addon** in Odoo (UI or CLI): ```bash odoo -d mydb -i itsulu_blog_publisher --stop-after-init ``` 4. **Configure API keys** in Odoo Settings → Technical → Parameters: - `itsulu_blog_publisher.anthropic_api_key` (if using Claude) - `itsulu_blog_publisher.openai_api_key` (if using OpenAI) - `itsulu_blog_publisher.gemini_api_key` (if using Gemini) - `itsulu_blog_publisher.ollama_base_url` (if using Ollama, e.g., `http://localhost:11434`) 5. **Configure notification emails** in Settings: - `itsulu_blog_publisher.notification_emails` (comma-separated list) ## Usage ### 1. Create a Blog Post On-Demand 1. Go to **Blog** → **Blog Publisher** → **Generate Now** 2. Enter topic/prompt 3. Select LLM provider and model 4. Choose auto-publish or draft 5. Click **Generate** The addon will: - Call the selected LLM provider - Create a blog.post with generated title, body, SEO fields - Generate social media copy for enabled platforms - Send notification email if published - Log tokens used, provider, model, and generation time ### 2. Schedule Automatic Generation 1. Go to **Blog** → **Blog Publisher** → **Schedule Slots** 2. Create/configure 3 slots: Morning, Afternoon, Evening 3. Set trigger time (UTC hours) 4. Choose LLM provider and model per slot 5. Enable auto-publish or save as draft 6. Save and activate The system will: - Run active slots at configured times via cron - Pull next topic from queue (if available) or LLM-chosen topic - Publish immediately or save for review - Send notification emails for published posts ### 3. Manage Topic Queue 1. Go to **Blog** → **Blog Publisher** → **Topics** 2. Create topics with title, notes, and priority (Urgent/High/Normal) 3. Set state to "Pending" 4. During generation, slots will consume pending topics in priority order 5. Topics move to "Used" state after generation ### 4. Monitor Generation Logs 1. Go to **Blog** → **Blog Publisher** → **Generation Logs** 2. View all generation attempts (success/error) 3. Check tokens used, provider, model, duration 4. Retry failed generations using **Retry** button ## Configuration ### Settings | Parameter | Type | Default | Description | |---|---|---|---| | `itsulu_blog_publisher.notification_emails` | Char | (empty) | Comma-separated email addresses for notifications | | `itsulu_blog_publisher.anthropic_api_key` | Char | (empty) | Anthropic API key for Claude models | | `itsulu_blog_publisher.openai_api_key` | Char | (empty) | OpenAI API key for ChatGPT models | | `itsulu_blog_publisher.gemini_api_key` | Char | (empty) | Google Gemini API key | | `itsulu_blog_publisher.ollama_base_url` | Char | (empty) | Base URL for local Ollama server | ### Email Template The addon includes a pre-configured email template (`email_template_blog_published`) that: - Displays blog post title and metadata - Includes social media copy for each enabled platform - Links to the published post - Shows generation stats (tokens, model, time) Customize by editing the template in **Email** → **Email Templates**. ## Architecture ### Models - **itsulu.blog.topic** — Topic queue with priority and state - **itsulu.blog.generation.log** — Audit trail for all generation attempts - **itsulu.blog.post.social** — Social media copy linked to blog posts - **itsulu.blog.schedule** — Configurable cron slots for scheduled generation ### Services - **llm_router.py** — Dispatcher that routes requests to provider APIs - **anthropic_provider.py** — Anthropic Claude integration - **openai_provider.py** — OpenAI ChatGPT integration - **gemini_provider.py** — Google Gemini integration - **ollama_provider.py** — Local Ollama model integration - **image_router.py** — Optional cover image generation (DALL·E, Imagen, Stable Diffusion) ## Development ### Running Tests ```bash # All tests pytest addons/itsulu_blog_publisher/tests/ -v # Specific test file pytest addons/itsulu_blog_publisher/tests/test_blog_topic.py -v # Specific test pytest addons/itsulu_blog_publisher/tests/test_blog_topic.py::TestBlogTopicPriority::test_get_next_topic_returns_highest_priority_pending_topic -v # BDD scenarios only pytest addons/itsulu_blog_publisher/tests/test_bdd_steps.py -v ``` ### TDD Workflow This project follows strict TDD discipline (see [CLAUDE.md](CLAUDE.md)): 1. **RED** — Write failing test 2. **GREEN** — Write minimum code to pass 3. **REFACTOR** — Clean up while test stays green 4. **REPEAT** — Next feature ### Code Quality Pre-commit hooks enforce: - Black code formatting - isort import sorting - pylint-odoo linting Run before committing: ```bash pre-commit run --all-files ``` ## Troubleshooting ### "Configuration error: API key not configured" **Cause**: API key parameter not set in Settings **Solution**: Go to Settings → Technical → Parameters and add the required key for your LLM provider ### "Unknown provider: " **Cause**: Provider name misspelled or provider not supported **Solution**: Use one of: `anthropic`, `openai`, `gemini`, `ollama` ### "No blog.post record was created" **Cause**: LLM response parsing failed or validation error **Check**: Generation log for error message; verify LLM response format ### "No email sent for published post" **Cause**: Notification email template not found or recipients not configured **Solution**: 1. Ensure template exists: **Email** → **Email Templates** → "Blog Post Published" 2. Set notification emails: **Settings** → Technical → Parameters → `itsulu_blog_publisher.notification_emails` ## Documentation - [CHANGELOG.md](CHANGELOG.md) — Release notes and version history - [CLAUDE.md](CLAUDE.md) — Complete TDD framework, testing patterns, versioning scheme, troubleshooting - [ARCHITECTURE.md](ARCHITECTURE.md) — System design, data flow, API contracts - [PHASE2_ROADMAP.md](PHASE2_ROADMAP.md) — Phase 2 implementation status ## License MIT License. See [LICENSE](LICENSE) for details. ## Support For issues, feature requests, or questions, open an issue on GitLab: https://gitlab.com/itsulu-odoo/itsulu-blog-publisher/issues ## Roadmap ### Phase 3 (Runboat E2E) - Playwright end-to-end scenarios - UI-driven generation workflow testing - Multi-user collaboration scenarios ### Phase 4 (Performance & Scale) - Query optimization (N+1 detection) - Batch generation for multiple topics - Template caching and pre-rendering - Performance benchmarks (throughput, latency) --- **Current Status**: v0.4.8 — test suite green (69/69 passing on ITSulu K8s) ✅ **Last Updated**: 2026-05-30 **Maintainer**: Nicholas Riegel (nicholasr@itsulu.com)