<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Gharis</title>
    <description>The latest articles on DEV Community by Muhammad Gharis (@muhammad_gharis_fe079470a).</description>
    <link>https://dev.to/muhammad_gharis_fe079470a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3972727%2F72333ae6-9d90-46a9-8f08-61572b66b3f8.jpg</url>
      <title>DEV Community: Muhammad Gharis</title>
      <link>https://dev.to/muhammad_gharis_fe079470a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/muhammad_gharis_fe079470a"/>
    <language>en</language>
    <item>
      <title>I Built a WhatsApp Native Helpdesk for Odoo Community</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Mon, 22 Jun 2026 22:50:14 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-a-whatsapp-native-helpdesk-for-odoo-community-4lg</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-a-whatsapp-native-helpdesk-for-odoo-community-4lg</guid>
      <description>&lt;h1&gt;
  
  
  I Built a WhatsApp Native Helpdesk for Odoo Community
&lt;/h1&gt;

&lt;p&gt;Most customer support systems still assume that customers want to open tickets by email.&lt;/p&gt;

&lt;p&gt;But in many markets, that is not how support actually happens.&lt;/p&gt;

&lt;p&gt;In Pakistan, MENA, South Asia, Africa, and many WhatsApp-first regions, customers usually do not start with a support portal or email thread.&lt;/p&gt;

&lt;p&gt;They send a WhatsApp message.&lt;/p&gt;

&lt;p&gt;That message becomes the real support request.&lt;/p&gt;

&lt;p&gt;The problem is that Odoo Community does not provide a complete WhatsApp-native helpdesk workflow out of the box.&lt;/p&gt;

&lt;p&gt;So I built an open-source module:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WhatsApp Native Helpdesk for Odoo Community&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitHub repo:&lt;br&gt;
&lt;a href="https://github.com/gharisj3/odoo-whatsapp-native-helpdesk" rel="noopener noreferrer"&gt;https://github.com/gharisj3/odoo-whatsapp-native-helpdesk&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Many small and mid-sized businesses already use Odoo Community for CRM, sales, accounting, inventory, and operations.&lt;/p&gt;

&lt;p&gt;But customer support often lives outside Odoo.&lt;/p&gt;

&lt;p&gt;Support messages are scattered across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp chats&lt;/li&gt;
&lt;li&gt;Agent phones&lt;/li&gt;
&lt;li&gt;Manual spreadsheets&lt;/li&gt;
&lt;li&gt;Email screenshots&lt;/li&gt;
&lt;li&gt;Internal notes&lt;/li&gt;
&lt;li&gt;Verbal follow-ups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a few serious problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No central ticket history&lt;/li&gt;
&lt;li&gt;No ownership&lt;/li&gt;
&lt;li&gt;No SLA visibility&lt;/li&gt;
&lt;li&gt;No escalation process&lt;/li&gt;
&lt;li&gt;No clean audit trail&lt;/li&gt;
&lt;li&gt;No connection between support and business records&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For WhatsApp-first businesses, the support channel is already clear.&lt;/p&gt;

&lt;p&gt;The missing piece is bringing that workflow into Odoo Community.&lt;/p&gt;


&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a WhatsApp-native support desk module for Odoo Community.&lt;/p&gt;

&lt;p&gt;The module allows businesses to receive WhatsApp customer messages, create or update support tickets in Odoo, assign tickets to agents, track status and SLA, and reply back to the customer through WhatsApp using n8n as the automation layer.&lt;/p&gt;

&lt;p&gt;The core flow is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer WhatsApp Message
        ↓
Meta WhatsApp Cloud API
        ↓
n8n Workflow
        ↓
Odoo Webhook
        ↓
Odoo Support Ticket
        ↓
Agent Reply from Odoo
        ↓
n8n Workflow
        ↓
WhatsApp Reply to Customer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal was not to build a chatbot.&lt;/p&gt;

&lt;p&gt;The goal was to build real support ticketing around the communication channel customers already use.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why n8n Is Used
&lt;/h2&gt;

&lt;p&gt;I used n8n as the integration layer because it keeps the WhatsApp API handling separate from Odoo.&lt;/p&gt;

&lt;p&gt;That means Odoo does not need to store Meta WhatsApp access tokens directly.&lt;/p&gt;

&lt;p&gt;n8n handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp webhook receiving&lt;/li&gt;
&lt;li&gt;Payload normalization&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API calls&lt;/li&gt;
&lt;li&gt;Status update routing&lt;/li&gt;
&lt;li&gt;Future automation workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Odoo handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ticket creation&lt;/li&gt;
&lt;li&gt;Customer mapping&lt;/li&gt;
&lt;li&gt;Agent assignment&lt;/li&gt;
&lt;li&gt;Message history&lt;/li&gt;
&lt;li&gt;SLA tracking&lt;/li&gt;
&lt;li&gt;Status management&lt;/li&gt;
&lt;li&gt;Internal support workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation makes the system easier to extend later.&lt;/p&gt;

&lt;p&gt;For example, the same pattern can be reused for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRM enrichment&lt;/li&gt;
&lt;li&gt;Invoice follow-ups&lt;/li&gt;
&lt;li&gt;Order status updates&lt;/li&gt;
&lt;li&gt;POS support&lt;/li&gt;
&lt;li&gt;Vendor workflows&lt;/li&gt;
&lt;li&gt;AI-assisted reply suggestions&lt;/li&gt;
&lt;li&gt;Customer satisfaction surveys&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;p&gt;The current version includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp-to-ticket creation&lt;/li&gt;
&lt;li&gt;Existing ticket update when the same customer replies&lt;/li&gt;
&lt;li&gt;Partner auto-mapping by phone number or WhatsApp ID&lt;/li&gt;
&lt;li&gt;Agent reply from inside Odoo&lt;/li&gt;
&lt;li&gt;Outbound WhatsApp message flow through n8n&lt;/li&gt;
&lt;li&gt;Message deduplication using WhatsApp message ID&lt;/li&gt;
&lt;li&gt;Ticket stages&lt;/li&gt;
&lt;li&gt;Team assignment&lt;/li&gt;
&lt;li&gt;Priority tracking&lt;/li&gt;
&lt;li&gt;SLA tracking&lt;/li&gt;
&lt;li&gt;First response tracking&lt;/li&gt;
&lt;li&gt;Failed message handling&lt;/li&gt;
&lt;li&gt;Retry action for failed outbound messages&lt;/li&gt;
&lt;li&gt;Message status sync&lt;/li&gt;
&lt;li&gt;Dashboard views&lt;/li&gt;
&lt;li&gt;Docker-based local setup&lt;/li&gt;
&lt;li&gt;Importable n8n workflow examples&lt;/li&gt;
&lt;li&gt;Postman API collection&lt;/li&gt;
&lt;li&gt;Security groups and access rules&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ticket Lifecycle
&lt;/h2&gt;

&lt;p&gt;A normal support flow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A customer sends a WhatsApp message.&lt;/li&gt;
&lt;li&gt;n8n receives the webhook from Meta WhatsApp Cloud API.&lt;/li&gt;
&lt;li&gt;n8n normalizes the payload.&lt;/li&gt;
&lt;li&gt;Odoo receives the payload through a secure webhook endpoint.&lt;/li&gt;
&lt;li&gt;Odoo checks whether the customer already exists.&lt;/li&gt;
&lt;li&gt;If the customer does not exist, Odoo creates a partner.&lt;/li&gt;
&lt;li&gt;Odoo checks whether there is an open ticket for that customer.&lt;/li&gt;
&lt;li&gt;If an open ticket exists, the message is added to the same ticket.&lt;/li&gt;
&lt;li&gt;If no open ticket exists, a new ticket is created.&lt;/li&gt;
&lt;li&gt;The support agent replies from Odoo.&lt;/li&gt;
&lt;li&gt;n8n sends the reply through WhatsApp Cloud API.&lt;/li&gt;
&lt;li&gt;Odoo stores the outbound message and delivery status.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This keeps the full conversation history inside Odoo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;For businesses that rely on WhatsApp, this kind of workflow can reduce a lot of operational friction.&lt;/p&gt;

&lt;p&gt;Instead of support being managed inside individual chat threads, it becomes structured.&lt;/p&gt;

&lt;p&gt;Agents can see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who owns the issue&lt;/li&gt;
&lt;li&gt;What the latest message was&lt;/li&gt;
&lt;li&gt;Whether the SLA is at risk&lt;/li&gt;
&lt;li&gt;Which stage the ticket is in&lt;/li&gt;
&lt;li&gt;Whether a reply failed&lt;/li&gt;
&lt;li&gt;Whether the issue was resolved&lt;/li&gt;
&lt;li&gt;Which customer record the issue belongs to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a big improvement over scattered WhatsApp conversations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository Structure
&lt;/h2&gt;

&lt;p&gt;The repository is organized as a real Odoo addon project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;odoo-whatsapp-native-helpdesk/
├── addons/
│   └── whatsapp_helpdesk/
├── n8n/
│   └── workflows/
├── docs/
├── postman/
├── scripts/
├── docker-compose.yml
├── Dockerfile
├── .env.example
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Odoo source code is not committed into the repository.&lt;/p&gt;

&lt;p&gt;The project includes bootstrap scripts and Docker setup so Odoo Community can be cloned and run locally during development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;The project uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo Community&lt;/li&gt;
&lt;li&gt;Python&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;Meta WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;REST webhooks&lt;/li&gt;
&lt;li&gt;XML views and security rules&lt;/li&gt;
&lt;li&gt;Postman for API testing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Local Setup
&lt;/h2&gt;

&lt;p&gt;Clone the repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/gharisj3/odoo-whatsapp-native-helpdesk.git
&lt;span class="nb"&gt;cd &lt;/span&gt;odoo-whatsapp-native-helpdesk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the environment file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make scripts executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x scripts/&lt;span class="k"&gt;*&lt;/span&gt;.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bootstrap Odoo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./scripts/bootstrap_odoo.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Odoo: http://localhost:8069
n8n:   http://localhost:5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Odoo Installation Flow
&lt;/h2&gt;

&lt;p&gt;After Odoo is running:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a new database.&lt;/li&gt;
&lt;li&gt;Activate developer mode.&lt;/li&gt;
&lt;li&gt;Update the Apps List.&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;WhatsApp Helpdesk&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install the module.&lt;/li&gt;
&lt;li&gt;Configure the WhatsApp Helpdesk channel.&lt;/li&gt;
&lt;li&gt;Import the n8n workflows.&lt;/li&gt;
&lt;li&gt;Test inbound and outbound flows.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  n8n Workflow Layer
&lt;/h2&gt;

&lt;p&gt;The project includes example n8n workflows for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inbound WhatsApp message to Odoo ticket&lt;/li&gt;
&lt;li&gt;Odoo agent reply to WhatsApp&lt;/li&gt;
&lt;li&gt;WhatsApp status update sync&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflows are designed as starting points.&lt;/p&gt;

&lt;p&gt;You still need to configure your own:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meta WhatsApp Cloud API credentials&lt;/li&gt;
&lt;li&gt;WhatsApp phone number ID&lt;/li&gt;
&lt;li&gt;Odoo base URL&lt;/li&gt;
&lt;li&gt;Shared secret&lt;/li&gt;
&lt;li&gt;Production webhook URLs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Security Design
&lt;/h2&gt;

&lt;p&gt;A few security choices were intentional:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meta access tokens are not stored in Odoo.&lt;/li&gt;
&lt;li&gt;WhatsApp API calls are handled by n8n.&lt;/li&gt;
&lt;li&gt;Webhook endpoints validate a shared secret.&lt;/li&gt;
&lt;li&gt;Real credentials are excluded from the repository.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env.example&lt;/code&gt; uses placeholder values only.&lt;/li&gt;
&lt;li&gt;Failed outbound messages are logged without exposing credentials.&lt;/li&gt;
&lt;li&gt;Internal notes are not sent to customers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For production, the setup should run behind HTTPS with proper reverse proxy configuration, strong passwords, and protected Odoo/n8n access.&lt;/p&gt;




&lt;h2&gt;
  
  
  Legal and Compliance Notes
&lt;/h2&gt;

&lt;p&gt;This is an independent open-source project.&lt;/p&gt;

&lt;p&gt;It is not an official Odoo, Meta, WhatsApp, or n8n product.&lt;/p&gt;

&lt;p&gt;It is not certified, endorsed, or sponsored by those companies.&lt;/p&gt;

&lt;p&gt;The names Odoo, WhatsApp, Meta, and n8n are used only to describe integration compatibility and the technologies involved.&lt;/p&gt;

&lt;p&gt;Production usage requires a valid Meta WhatsApp Cloud API setup and compliance with applicable WhatsApp Business Platform rules, messaging policies, customer consent requirements, and local laws.&lt;/p&gt;

&lt;p&gt;This project does not bypass WhatsApp Business Platform rules.&lt;/p&gt;

&lt;p&gt;Businesses are responsible for using approved templates where required and for following customer messaging policies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current Limitations
&lt;/h2&gt;

&lt;p&gt;The current release focuses on the core support workflow.&lt;/p&gt;

&lt;p&gt;Some items are planned for future versions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Media attachment handling&lt;/li&gt;
&lt;li&gt;WhatsApp template message support&lt;/li&gt;
&lt;li&gt;Multi-number routing&lt;/li&gt;
&lt;li&gt;Customer satisfaction survey&lt;/li&gt;
&lt;li&gt;AI-assisted reply suggestions&lt;/li&gt;
&lt;li&gt;Auto-priority classification&lt;/li&gt;
&lt;li&gt;Working-hours SLA calendar&lt;/li&gt;
&lt;li&gt;CRM and sales order linking&lt;/li&gt;
&lt;li&gt;Shopify or WooCommerce lookup through n8n&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;I work around ERP, Odoo, backend systems, and automation workflows.&lt;/p&gt;

&lt;p&gt;I kept seeing the same gap:&lt;/p&gt;

&lt;p&gt;Businesses were running operations in Odoo, but support conversations were happening somewhere else.&lt;/p&gt;

&lt;p&gt;For WhatsApp-first markets, that gap matters.&lt;/p&gt;

&lt;p&gt;This project is my attempt to make that support flow more structured, traceable, and automation-ready while still keeping it open-source friendly.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Repository
&lt;/h2&gt;

&lt;p&gt;You can check the project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/odoo-whatsapp-native-helpdesk" rel="noopener noreferrer"&gt;https://github.com/gharisj3/odoo-whatsapp-native-helpdesk&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More From Me
&lt;/h2&gt;

&lt;p&gt;LinkedIn:&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fiverr:&lt;br&gt;
&lt;a href="https://www.fiverr.com/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/muhammadghar709&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Digital products and templates:&lt;br&gt;
&lt;a href="https://omniacademy.gumroad.com/" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;WhatsApp is not just a chat app for many businesses.&lt;/p&gt;

&lt;p&gt;It is where support starts.&lt;/p&gt;

&lt;p&gt;The next step is making those conversations structured enough to manage, assign, track, and improve.&lt;/p&gt;

&lt;p&gt;That is what this project is built for.&lt;/p&gt;

</description>
      <category>odoo</category>
      <category>n8nbrightdatachallenge</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>Why ERP Go-Live Fails Without a Command Center</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:05:00 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/why-erp-go-live-fails-without-a-command-center-4056</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/why-erp-go-live-fails-without-a-command-center-4056</guid>
      <description>&lt;p&gt;ERP implementation does not usually fail because of one big issue.&lt;/p&gt;

&lt;p&gt;It usually fails because many small issues are not tracked properly.&lt;/p&gt;

&lt;p&gt;During go-live, teams are dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;open issues&lt;/li&gt;
&lt;li&gt;UAT feedback&lt;/li&gt;
&lt;li&gt;user sign-offs&lt;/li&gt;
&lt;li&gt;cutover activities&lt;/li&gt;
&lt;li&gt;data migration tasks&lt;/li&gt;
&lt;li&gt;access rights checks&lt;/li&gt;
&lt;li&gt;business confirmations&lt;/li&gt;
&lt;li&gt;pending reports&lt;/li&gt;
&lt;li&gt;integration readiness&lt;/li&gt;
&lt;li&gt;support responsibilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If these items are not clearly tracked, the go-live phase becomes stressful very quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with ERP go-live
&lt;/h2&gt;

&lt;p&gt;A go-live phase needs discipline.&lt;/p&gt;

&lt;p&gt;Without a structured tracker, teams may struggle with questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which issues are still open?&lt;/li&gt;
&lt;li&gt;Who owns each action item?&lt;/li&gt;
&lt;li&gt;Has UAT been signed off?&lt;/li&gt;
&lt;li&gt;Which reports are pending?&lt;/li&gt;
&lt;li&gt;Are integrations ready?&lt;/li&gt;
&lt;li&gt;Is the cutover plan approved?&lt;/li&gt;
&lt;li&gt;Which tasks are critical before go-live?&lt;/li&gt;
&lt;li&gt;Who confirmed the final business readiness?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For systems like Odoo ERP, even a small missed configuration, access rule, or data issue can create operational problems after launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a command center should include
&lt;/h2&gt;

&lt;p&gt;A simple ERP go-live command center should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;go-live checklist&lt;/li&gt;
&lt;li&gt;cutover plan&lt;/li&gt;
&lt;li&gt;UAT issue tracker&lt;/li&gt;
&lt;li&gt;sign-off tracker&lt;/li&gt;
&lt;li&gt;open issues log&lt;/li&gt;
&lt;li&gt;responsible owner column&lt;/li&gt;
&lt;li&gt;priority and status fields&lt;/li&gt;
&lt;li&gt;final readiness review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives the implementation team and business stakeholders one place to track readiness.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I created an &lt;strong&gt;Odoo ERP Go-Live Command Center Pack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is designed for consultants, implementation teams, ERP users, and small businesses preparing for an Odoo go-live.&lt;/p&gt;

&lt;p&gt;The pack includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;go-live checklist&lt;/li&gt;
&lt;li&gt;cutover planning template&lt;/li&gt;
&lt;li&gt;UAT issue tracker&lt;/li&gt;
&lt;li&gt;sign-off templates&lt;/li&gt;
&lt;li&gt;open issue tracking structure&lt;/li&gt;
&lt;li&gt;readiness documentation format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to reduce confusion during go-live and give teams a simple structure to manage the final stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is useful for
&lt;/h2&gt;

&lt;p&gt;This can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo consultants&lt;/li&gt;
&lt;li&gt;ERP implementation teams&lt;/li&gt;
&lt;li&gt;business users&lt;/li&gt;
&lt;li&gt;project managers&lt;/li&gt;
&lt;li&gt;SMEs going live with ERP&lt;/li&gt;
&lt;li&gt;support teams&lt;/li&gt;
&lt;li&gt;functional consultants&lt;/li&gt;
&lt;li&gt;technical consultants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed the ready-made pack on Gumroad for anyone working around Odoo ERP implementation or go-live planning.&lt;/p&gt;

&lt;p&gt;Check it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/hjacq" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/hjacq&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>erp</category>
      <category>odoo</category>
      <category>uat</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built an n8n Client Intake Workflow Pack with Google Sheets CRM and WhatsApp Follow-Up Structure</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:04:08 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-an-n8n-client-intake-workflow-pack-with-google-sheets-crm-and-whatsapp-follow-up-structure-4d12</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-an-n8n-client-intake-workflow-pack-with-google-sheets-crm-and-whatsapp-follow-up-structure-4d12</guid>
      <description>&lt;p&gt;Client intake is one of the most underrated parts of freelancing and agency work.&lt;/p&gt;

&lt;p&gt;Many service providers can deliver the work, but their intake process is messy.&lt;/p&gt;

&lt;p&gt;A typical flow looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client sends a WhatsApp message&lt;/li&gt;
&lt;li&gt;requirements are discussed in chat&lt;/li&gt;
&lt;li&gt;important details get buried&lt;/li&gt;
&lt;li&gt;no proper CRM record is created&lt;/li&gt;
&lt;li&gt;follow-up dates are forgotten&lt;/li&gt;
&lt;li&gt;onboarding steps are repeated manually&lt;/li&gt;
&lt;li&gt;client information is scattered across messages, emails, and sheets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates confusion before the actual work even starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When client intake is not structured, it affects everything after that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unclear requirements&lt;/li&gt;
&lt;li&gt;missed follow-ups&lt;/li&gt;
&lt;li&gt;poor project handover&lt;/li&gt;
&lt;li&gt;delayed proposals&lt;/li&gt;
&lt;li&gt;weak client experience&lt;/li&gt;
&lt;li&gt;no central tracking sheet&lt;/li&gt;
&lt;li&gt;repeated manual work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For freelancers and small agencies, this can directly affect sales and delivery quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  The simple workflow idea
&lt;/h2&gt;

&lt;p&gt;A better client intake system should help you:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;collect client details&lt;/li&gt;
&lt;li&gt;store them in a tracker&lt;/li&gt;
&lt;li&gt;assign status and priority&lt;/li&gt;
&lt;li&gt;document requirements&lt;/li&gt;
&lt;li&gt;prepare follow-up actions&lt;/li&gt;
&lt;li&gt;create a basic CRM-style view&lt;/li&gt;
&lt;li&gt;use reusable messages and prompts&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This does not always require a complex SaaS tool.&lt;/p&gt;

&lt;p&gt;A simple combination of n8n, Google Sheets, WhatsApp follow-up structure, and documentation can be enough for many small teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I created an &lt;strong&gt;n8n Client Intake Workflow Pack&lt;/strong&gt; for freelancers, agencies, consultants, and automation builders.&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client intake workflow structure&lt;/li&gt;
&lt;li&gt;Google Sheets CRM tracker idea&lt;/li&gt;
&lt;li&gt;WhatsApp follow-up automation structure&lt;/li&gt;
&lt;li&gt;setup guide&lt;/li&gt;
&lt;li&gt;client tracking format&lt;/li&gt;
&lt;li&gt;reusable workflow documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to help small teams organize client intake without starting from zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is useful for
&lt;/h2&gt;

&lt;p&gt;This can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freelancers&lt;/li&gt;
&lt;li&gt;consultants&lt;/li&gt;
&lt;li&gt;small agencies&lt;/li&gt;
&lt;li&gt;automation service providers&lt;/li&gt;
&lt;li&gt;virtual assistants&lt;/li&gt;
&lt;li&gt;business operations teams&lt;/li&gt;
&lt;li&gt;people learning n8n workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed the ready-made pack on Gumroad for anyone who wants to check it out.&lt;/p&gt;

&lt;p&gt;Link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/jdbaw" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/jdbaw&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>n8nbrightdatachallenge</category>
      <category>crm</category>
      <category>whatsapp</category>
      <category>ai</category>
    </item>
    <item>
      <title>25 No-Code Automation Ideas for Freelancers, Agencies and Small Businesses</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 08:03:04 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/25-no-code-automation-ideas-for-freelancers-agencies-and-small-businesses-16ce</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/25-no-code-automation-ideas-for-freelancers-agencies-and-small-businesses-16ce</guid>
      <description>&lt;p&gt;Many people want to start using automation, but they get stuck at the same point:&lt;/p&gt;

&lt;p&gt;They do not know what to automate first.&lt;/p&gt;

&lt;p&gt;The problem is not always the tool.&lt;/p&gt;

&lt;p&gt;The problem is choosing the right workflow.&lt;/p&gt;

&lt;p&gt;A freelancer, agency, or small business may use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp&lt;/li&gt;
&lt;li&gt;Google Sheets&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;forms&lt;/li&gt;
&lt;li&gt;invoices&lt;/li&gt;
&lt;li&gt;CRM notes&lt;/li&gt;
&lt;li&gt;client onboarding documents&lt;/li&gt;
&lt;li&gt;task trackers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But without a clear automation checklist, everything stays manual.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common manual problems
&lt;/h2&gt;

&lt;p&gt;Small teams usually waste time on tasks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;copying client details from messages to spreadsheets&lt;/li&gt;
&lt;li&gt;sending the same follow-up message again and again&lt;/li&gt;
&lt;li&gt;forgetting invoice reminders&lt;/li&gt;
&lt;li&gt;tracking leads manually&lt;/li&gt;
&lt;li&gt;creating client handover notes from scratch&lt;/li&gt;
&lt;li&gt;checking forms and updating sheets&lt;/li&gt;
&lt;li&gt;repeating onboarding steps for every client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tasks are small individually, but together they consume hours every week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I created this checklist
&lt;/h2&gt;

&lt;p&gt;I created a &lt;strong&gt;Free AI Automation Workflow Checklist&lt;/strong&gt; with 25 no-code automation ideas.&lt;/p&gt;

&lt;p&gt;The purpose is simple:&lt;/p&gt;

&lt;p&gt;Help freelancers, consultants, agencies, and small businesses identify practical automation opportunities without overcomplicating the process.&lt;/p&gt;

&lt;p&gt;This is not about building a massive system.&lt;/p&gt;

&lt;p&gt;It is about finding small workflows that can save time immediately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example automation ideas
&lt;/h2&gt;

&lt;p&gt;Some useful workflow categories include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lead capture automation&lt;/li&gt;
&lt;li&gt;client intake automation&lt;/li&gt;
&lt;li&gt;CRM update automation&lt;/li&gt;
&lt;li&gt;invoice reminder automation&lt;/li&gt;
&lt;li&gt;follow-up automation&lt;/li&gt;
&lt;li&gt;onboarding automation&lt;/li&gt;
&lt;li&gt;handover documentation automation&lt;/li&gt;
&lt;li&gt;Google Sheets tracking automation&lt;/li&gt;
&lt;li&gt;AI prompt-based content or data processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple checklist can help you decide what to automate first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who can use this
&lt;/h2&gt;

&lt;p&gt;This checklist is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freelancers&lt;/li&gt;
&lt;li&gt;consultants&lt;/li&gt;
&lt;li&gt;small agencies&lt;/li&gt;
&lt;li&gt;beginner automation builders&lt;/li&gt;
&lt;li&gt;no-code learners&lt;/li&gt;
&lt;li&gt;small business owners&lt;/li&gt;
&lt;li&gt;virtual assistants&lt;/li&gt;
&lt;li&gt;operations teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed it on Gumroad as a free / pay-what-you-want resource.&lt;/p&gt;

&lt;p&gt;You can check it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/sexej" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/sexej&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>ai</category>
      <category>requestforpost</category>
      <category>automaton</category>
    </item>
    <item>
      <title>I Built a Simple AI Lead Qualification CRM Workflow Pack for Freelancers and Small Teams</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 14 Jun 2026 07:41:08 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-a-simple-ai-lead-qualification-crm-workflow-pack-for-freelancers-and-small-teams-2c8o</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-a-simple-ai-lead-qualification-crm-workflow-pack-for-freelancers-and-small-teams-2c8o</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Simple AI Lead Qualification CRM Workflow Pack for Freelancers and Small Teams
&lt;/h1&gt;

&lt;p&gt;Most freelancers, agencies, consultants, and small businesses do not lose leads because they are bad at selling.&lt;/p&gt;

&lt;p&gt;They lose leads because their follow-up system is weak.&lt;/p&gt;

&lt;p&gt;A common situation looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;leads come from LinkedIn, WhatsApp, email, forms, or referrals&lt;/li&gt;
&lt;li&gt;notes are saved in random chats&lt;/li&gt;
&lt;li&gt;follow-ups are forgotten&lt;/li&gt;
&lt;li&gt;lead quality is not scored properly&lt;/li&gt;
&lt;li&gt;there is no simple CRM pipeline&lt;/li&gt;
&lt;li&gt;every new client inquiry starts from zero again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Large CRM tools are useful, but many small teams do not need a complex SaaS system on day one.&lt;/p&gt;

&lt;p&gt;They need a lightweight system that helps them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;capture leads&lt;/li&gt;
&lt;li&gt;qualify leads&lt;/li&gt;
&lt;li&gt;score lead quality&lt;/li&gt;
&lt;li&gt;track follow-ups&lt;/li&gt;
&lt;li&gt;move leads through a pipeline&lt;/li&gt;
&lt;li&gt;reuse AI prompts for lead analysis&lt;/li&gt;
&lt;li&gt;document the sales process clearly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built a practical &lt;strong&gt;AI Lead Qualification CRM Workflow Pack&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the pack includes
&lt;/h2&gt;

&lt;p&gt;This pack is designed for freelancers, consultants, agencies, and small businesses that want a simple AI-assisted lead qualification workflow.&lt;/p&gt;

&lt;p&gt;It includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n8n lead qualification workflow idea&lt;/li&gt;
&lt;li&gt;lead scoring sheet&lt;/li&gt;
&lt;li&gt;CRM pipeline template&lt;/li&gt;
&lt;li&gt;AI prompt pack for lead analysis&lt;/li&gt;
&lt;li&gt;follow-up tracking structure&lt;/li&gt;
&lt;li&gt;simple workflow documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to replace a full CRM platform.&lt;/p&gt;

&lt;p&gt;The goal is to help small teams organize leads before they become messy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;In real freelance and agency work, most missed opportunities come from poor tracking.&lt;/p&gt;

&lt;p&gt;A lead may be interested today, but if nobody follows up after 2 days, that opportunity becomes cold.&lt;/p&gt;

&lt;p&gt;A simple workflow can make a big difference:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture the lead&lt;/li&gt;
&lt;li&gt;Score the lead&lt;/li&gt;
&lt;li&gt;Add notes&lt;/li&gt;
&lt;li&gt;Assign a follow-up date&lt;/li&gt;
&lt;li&gt;Move the lead through stages&lt;/li&gt;
&lt;li&gt;Reuse AI prompts to analyze intent and priority&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This kind of structure saves time and reduces manual decision-making.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who this is useful for
&lt;/h2&gt;

&lt;p&gt;This can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;freelancers&lt;/li&gt;
&lt;li&gt;solo consultants&lt;/li&gt;
&lt;li&gt;small agencies&lt;/li&gt;
&lt;li&gt;service providers&lt;/li&gt;
&lt;li&gt;automation builders&lt;/li&gt;
&lt;li&gt;CRM beginners&lt;/li&gt;
&lt;li&gt;people selling digital or professional services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have listed this as a small paid digital product on Gumroad for anyone who wants to use the ready-made version instead of building it from scratch.&lt;/p&gt;

&lt;p&gt;Check it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/pkybo" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com/l/pkybo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect with me
&lt;/h2&gt;

&lt;p&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;https://omniacademy.gumroad.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;https://github.com/gharisj3&lt;/a&gt;&lt;br&gt;&lt;br&gt;
LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Contra: &lt;a href="https://contra.com/muhammad_gharis_j2g71vgn" rel="noopener noreferrer"&gt;https://contra.com/muhammad_gharis_j2g71vgn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Fiverr: &lt;a href="https://www.fiverr.com/sellers/muhammadghar709" rel="noopener noreferrer"&gt;https://www.fiverr.com/sellers/muhammadghar709&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Email: &lt;a href="mailto:gharis@omni-academy.com"&gt;gharis@omni-academy.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crm</category>
      <category>tooling</category>
      <category>freelance</category>
    </item>
    <item>
      <title>How I Built an AI Business Automation Workflow Pack with n8n, Google Sheets and JSON Templates</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Thu, 11 Jun 2026 15:30:25 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/how-i-built-an-ai-business-automation-workflow-pack-with-n8n-google-sheets-and-json-templates-5f1c</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/how-i-built-an-ai-business-automation-workflow-pack-with-n8n-google-sheets-and-json-templates-5f1c</guid>
      <description>&lt;h1&gt;
  
  
  How I Built an AI Business Automation Workflow Pack with n8n, Google Sheets and JSON Templates
&lt;/h1&gt;

&lt;p&gt;Most business automation ideas sound simple at the start:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Capture a lead, save it somewhere, send a reply, and follow up later.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But when you try to build it properly for a real client or business, the workflow becomes more serious.&lt;/p&gt;

&lt;p&gt;You need to think about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How the lead data enters the system&lt;/li&gt;
&lt;li&gt;Where the data is stored&lt;/li&gt;
&lt;li&gt;What happens if a field is missing&lt;/li&gt;
&lt;li&gt;How the AI response is generated&lt;/li&gt;
&lt;li&gt;How follow-ups are tracked&lt;/li&gt;
&lt;li&gt;What happens if an API fails&lt;/li&gt;
&lt;li&gt;How the client will understand and maintain the workflow later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why I decided to build a structured &lt;strong&gt;AI Business Automation Workflow Pack&lt;/strong&gt; using n8n-style workflow templates, Google Sheets-style CRM trackers, JSON workflow files, prompt templates, testing checklists, and client handover documents.&lt;/p&gt;

&lt;p&gt;This post explains the thinking behind it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Wanted to Solve
&lt;/h2&gt;

&lt;p&gt;Many freelancers and small businesses want automation, but they usually do not need a huge CRM or expensive SaaS setup at the beginning.&lt;/p&gt;

&lt;p&gt;They need something practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capture leads from forms or webhooks&lt;/li&gt;
&lt;li&gt;Store inquiries in a simple CRM tracker&lt;/li&gt;
&lt;li&gt;Draft AI-assisted replies&lt;/li&gt;
&lt;li&gt;Follow up with leads&lt;/li&gt;
&lt;li&gt;Track invoice/payment reminders&lt;/li&gt;
&lt;li&gt;Triage support messages&lt;/li&gt;
&lt;li&gt;Deliver the workflow to a client professionally&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real pain is not just building one automation.&lt;/p&gt;

&lt;p&gt;The real pain is building a repeatable system that can be reused across clients and projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Stack
&lt;/h2&gt;

&lt;p&gt;For this product, I designed the pack around a simple and practical stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook / Form Input
        ↓
n8n Workflow Template
        ↓
Data Cleaning / Validation
        ↓
AI Prompt / Reply Draft
        ↓
Google Sheets-style CRM Tracker
        ↓
Email / Follow-Up / Client Output
        ↓
Testing + Handover Documentation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal was to make each workflow easy to understand, modify, and reuse.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Pack Includes
&lt;/h2&gt;

&lt;p&gt;I structured the product into several parts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. n8n workflow JSON templates
2. Google Sheets-style CRM trackers
3. AI prompt templates
4. PDF setup guides
5. Testing checklists
6. Error handling checklists
7. Client handover documents
8. README and license files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is that a freelancer or automation consultant can use the pack as a starting point instead of creating everything from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 1: Lead Intake to CRM Tracker
&lt;/h2&gt;

&lt;p&gt;The first workflow is a simple lead intake flow.&lt;/p&gt;

&lt;p&gt;The structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Webhook receives lead
        ↓
Validate required fields
        ↓
Normalize name, email, phone, source
        ↓
Assign lead status
        ↓
Save to CRM tracker
        ↓
Return success response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example lead data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Smith"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+123456789"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Website Form"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I need automation for my business"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow is designed to make sure every lead has a proper structure before it is stored.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 2: Contact Form to Google Sheets + Email Alert
&lt;/h2&gt;

&lt;p&gt;This workflow is useful for small businesses that receive contact form messages.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Contact form submission
        ↓
Clean message text
        ↓
Store submission
        ↓
Prepare internal notification
        ↓
Send email alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part here is not just sending an email.&lt;/p&gt;

&lt;p&gt;The important part is keeping a proper record of every inquiry so nothing gets lost.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 3: AI Email Reply Draft
&lt;/h2&gt;

&lt;p&gt;This is one of the most useful workflows in the pack.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client message received
        ↓
Send message to AI prompt
        ↓
Generate professional reply draft
        ↓
Save draft to tracker
        ↓
Human reviews before sending
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I intentionally designed this as a &lt;strong&gt;draft workflow&lt;/strong&gt;, not a fully automatic send workflow.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because AI-generated replies should usually be reviewed before sending to a real client, especially in business communication.&lt;/p&gt;

&lt;p&gt;Example output structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sales_inquiry"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"suggested_reply"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thank you for reaching out. I would be happy to understand your automation requirements..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"schedule_discovery_call"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.86&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the workflow safer and more professional.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 4: Client Follow-Up Reminder
&lt;/h2&gt;

&lt;p&gt;Follow-ups are where many freelancers and small businesses lose money.&lt;/p&gt;

&lt;p&gt;A lead comes in, the client sounds interested, then nobody follows up.&lt;/p&gt;

&lt;p&gt;The workflow logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read lead tracker
        ↓
Find pending follow-ups
        ↓
Check last contact date
        ↓
Prepare follow-up message
        ↓
Update follow-up status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple follow-up tracker can include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lead Name
Email
Phone
Status
Last Contact Date
Next Follow-Up Date
Follow-Up Message
Assigned Person
Notes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be very useful for freelancers, agencies, and small sales teams.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 5: Invoice / Payment Reminder
&lt;/h2&gt;

&lt;p&gt;This workflow is designed for overdue invoice reminders.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read invoice tracker
        ↓
Find unpaid invoices
        ↓
Check due date
        ↓
Generate polite reminder message
        ↓
Prepare email or message output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example reminder logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If due date is passed and payment status is unpaid:
    Prepare reminder
Else:
    Do nothing
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is simple, but very practical.&lt;/p&gt;

&lt;p&gt;Many freelancers do not need advanced accounting software in the beginning. They just need a clean way to track pending payments and follow up professionally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 6: Support Ticket Triage
&lt;/h2&gt;

&lt;p&gt;The final workflow is for support requests.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Support request received
        ↓
Classify category
        ↓
Detect priority
        ↓
Generate suggested response
        ↓
Log ticket status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example categories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Billing
Technical Issue
Feature Request
Account Access
General Question
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example priority levels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Low
Medium
High
Critical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This type of workflow is useful for agencies, SaaS teams, support teams, and service businesses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Used JSON Templates
&lt;/h2&gt;

&lt;p&gt;JSON templates make workflow packaging easier because they can be imported, reviewed, versioned, and reused.&lt;/p&gt;

&lt;p&gt;For automation builders, this is useful because the workflow is not just a screenshot or idea.&lt;/p&gt;

&lt;p&gt;It becomes a file that can be copied, modified, tested, and improved.&lt;/p&gt;

&lt;p&gt;A good workflow template should include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clear node names
Placeholder credentials
No real API keys
Sample test data
Documentation notes
Error handling path
Clean workflow structure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used placeholders like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YOUR_API_KEY_HERE
YOUR_WEBHOOK_URL_HERE
YOUR_SHEET_ID_HERE
YOUR_EMAIL_HERE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never include real credentials in a template product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Included Google Sheets-Style Trackers
&lt;/h2&gt;

&lt;p&gt;Not every small business wants to pay for a CRM immediately.&lt;/p&gt;

&lt;p&gt;A spreadsheet can work well for early-stage workflows.&lt;/p&gt;

&lt;p&gt;The CRM tracker structure includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Leads
Contacts
Companies
Follow-Ups
Automation Logs
Email Drafts
Status Dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives users a simple place to store and review automation output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Testing Checklists Matter
&lt;/h2&gt;

&lt;p&gt;A workflow is not production-ready just because it runs once.&lt;/p&gt;

&lt;p&gt;Before using an automation with a real client, I like to test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Required fields
Invalid email format
Duplicate records
API failure
Empty response
Wrong data type
Webhook response
Sheet writing
Email output
End-to-end flow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is why I included workflow testing and error handling checklists in the pack.&lt;/p&gt;

&lt;p&gt;A good automation product should not only help users build faster. It should help them build safer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned While Building This
&lt;/h2&gt;

&lt;p&gt;Here are the biggest lessons from creating this kind of automation pack:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Generic workflows are not enough
&lt;/h3&gt;

&lt;p&gt;A workflow is more valuable when it comes with setup guides, checklists, trackers, and handover documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. AI should support humans, not replace review
&lt;/h3&gt;

&lt;p&gt;For email replies, proposals, and client communication, AI drafts should usually be reviewed before sending.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Templates need placeholders, not secrets
&lt;/h3&gt;

&lt;p&gt;Never include real credentials, API keys, tokens, or client data.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Small businesses prefer simple systems
&lt;/h3&gt;

&lt;p&gt;A clear spreadsheet plus a workflow is sometimes more useful than a complex SaaS setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Documentation increases trust
&lt;/h3&gt;

&lt;p&gt;If a client cannot understand the automation, they will not feel comfortable using it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Type of Pack Is Useful For
&lt;/h2&gt;

&lt;p&gt;This kind of workflow pack can help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Freelancers
Automation consultants
n8n builders
Virtual assistants
Small agencies
Startup operators
Small business owners
Backend developers
AI automation service providers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main use case is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build client-ready business automations faster without starting from zero every time.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What I Published
&lt;/h2&gt;

&lt;p&gt;I packaged the full version as a digital product here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://omniacademy.gumroad.com/l/qwajt?layout=profile" rel="noopener noreferrer"&gt;AI Business Automation Workflow Pack — n8n Templates, Google Sheets CRM &amp;amp; Client Automation Kit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;6 workflow templates
CRM tracker templates
AI prompt templates
PDF setup guides
Testing checklists
Error handling checklist
Client handover documents
README and license files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disclosure: This is my own digital product from Omni Academy Consulting and Technologies. The article is written to share the build process and structure behind the product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Connect With Me
&lt;/h2&gt;

&lt;p&gt;You can also connect with me here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LinkedIn: &lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;LinkedIn Profile&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Gumroad: &lt;a href="https://omniacademy.gumroad.com" rel="noopener noreferrer"&gt;Omni Academy Consulting and Technologies&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AI automation is not only about connecting tools.&lt;/p&gt;

&lt;p&gt;It is about designing a repeatable business process.&lt;/p&gt;

&lt;p&gt;A strong automation workflow should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Understandable
Testable
Documented
Safe
Reusable
Client-ready
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the standard I tried to follow while building this pack.&lt;/p&gt;

&lt;p&gt;If you are building automation products or client workflows, my advice is simple:&lt;/p&gt;

&lt;p&gt;Do not only build the workflow.&lt;/p&gt;

&lt;p&gt;Build the system around the workflow.&lt;/p&gt;

</description>
      <category>n8n</category>
      <category>automation</category>
      <category>ai</category>
      <category>freelance</category>
    </item>
    <item>
      <title>Why Your AI-Connected ERP Will Fail in Production And How to Fix It Before It Does</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:56:06 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/why-your-ai-connected-erp-will-fail-in-production-and-how-to-fix-it-before-it-does-306o</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/why-your-ai-connected-erp-will-fail-in-production-and-how-to-fix-it-before-it-does-306o</guid>
      <description>&lt;p&gt;Most AI + ERP integrations fail in production not because the AI model is weak, but because there is no validation layer between the LLM output and the database.&lt;/p&gt;

&lt;p&gt;Raw AI responses should never go directly into ERP fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The demo problem: AI works perfectly in a controlled example&lt;/li&gt;
&lt;li&gt;The production problem: real data is messy and LLM output is unpredictable&lt;/li&gt;
&lt;li&gt;Example failure: hallucinated vendor name in accounts payable&lt;/li&gt;
&lt;li&gt;Why direct AI → ERP writes are dangerous&lt;/li&gt;
&lt;li&gt;The fix: FastAPI middleware + Pydantic v2 validation&lt;/li&gt;
&lt;li&gt;Code example: validated AI response schema&lt;/li&gt;
&lt;li&gt;Code example: FastAPI endpoint returning structured output&lt;/li&gt;
&lt;li&gt;Production pattern: AI → validation → workflow → ERP&lt;/li&gt;
&lt;li&gt;Error handling: log failure instead of corrupting records&lt;/li&gt;
&lt;li&gt;Repo reference: omni-odoo-stack&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Suggested CTA
&lt;/h3&gt;

&lt;p&gt;I built this pattern into my open-source Odoo automation repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;https://github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Post 3
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Title
&lt;/h3&gt;

&lt;p&gt;How to Build a WhatsApp to CRM Pipeline with n8n and Odoo 19&lt;/p&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;n8n&lt;/code&gt;, &lt;code&gt;odoo&lt;/code&gt;, &lt;code&gt;automation&lt;/code&gt;, &lt;code&gt;webhooks&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;Every WhatsApp message from a potential client should create a CRM lead automatically.&lt;/p&gt;

&lt;p&gt;Here is the architecture I use to make that happen with n8n, Odoo, and WhatsApp Cloud API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Can Perform Well
&lt;/h3&gt;

&lt;p&gt;WhatsApp automation is highly practical.&lt;/p&gt;

&lt;p&gt;Odoo + WhatsApp tutorials are limited.&lt;/p&gt;

&lt;p&gt;n8n users actively search for CRM, webhook, WhatsApp, and API automation examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  Core Angle
&lt;/h3&gt;

&lt;p&gt;Show a practical architecture for turning WhatsApp conversations into CRM leads using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Meta WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;n8n webhook trigger&lt;/li&gt;
&lt;li&gt;Odoo CRM&lt;/li&gt;
&lt;li&gt;FastAPI AI lead scoring&lt;/li&gt;
&lt;li&gt;duplicate prevention&lt;/li&gt;
&lt;li&gt;error logging&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Why WhatsApp is a serious business intake channel&lt;/li&gt;
&lt;li&gt;What you need:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Meta Business account&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;self-hosted n8n&lt;/li&gt;
&lt;li&gt;Odoo 19&lt;/li&gt;
&lt;li&gt;optional FastAPI AI middleware

&lt;ol&gt;
&lt;li&gt;Step 1: WhatsApp webhook setup&lt;/li&gt;
&lt;li&gt;Step 2: n8n webhook trigger&lt;/li&gt;
&lt;li&gt;Step 3: parse phone number, message body, and message ID&lt;/li&gt;
&lt;li&gt;Step 4: duplicate prevention using message ID&lt;/li&gt;
&lt;li&gt;Step 5: call AI scoring middleware&lt;/li&gt;
&lt;li&gt;Step 6: create CRM lead in Odoo&lt;/li&gt;
&lt;li&gt;Step 7: send WhatsApp confirmation&lt;/li&gt;
&lt;li&gt;Step 8: log success or failure&lt;/li&gt;
&lt;li&gt;Full workflow JSON available in repo&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Wording Change
&lt;/h3&gt;

&lt;p&gt;Avoid:&lt;/p&gt;

&lt;p&gt;“No Code”&lt;/p&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;p&gt;“No Zapier, No Monthly Automation Fees”&lt;/p&gt;

&lt;p&gt;Because the workflow still requires API setup, webhook configuration, and Odoo endpoint understanding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Suggested CTA
&lt;/h3&gt;

&lt;p&gt;The full workflow JSON is available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;https://github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Post 4
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Title
&lt;/h3&gt;

&lt;p&gt;Self-Hosting Odoo 19 on Oracle OCI Free Tier — Complete Setup Guide&lt;/p&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;odoo&lt;/code&gt;, &lt;code&gt;docker&lt;/code&gt;, &lt;code&gt;oracle&lt;/code&gt;, &lt;code&gt;devops&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;Odoo hosting can cost $50–200/month on typical VPS or managed platforms.&lt;/p&gt;

&lt;p&gt;Oracle OCI Always Free gives developers a powerful free-tier path for self-hosted ERP experiments.&lt;/p&gt;

&lt;p&gt;Here is the setup approach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important Warning Before Publishing
&lt;/h3&gt;

&lt;p&gt;Do not publish this as a “complete guide” until you have actually deployed and boot-tested Odoo on OCI.&lt;/p&gt;

&lt;p&gt;This post will attract people who copy commands directly.&lt;/p&gt;

&lt;p&gt;If the guide is not tested, it can hurt your credibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safer Title Until Tested
&lt;/h3&gt;

&lt;p&gt;How I Plan to Self-Host Odoo 19 on Oracle OCI Free Tier&lt;/p&gt;

&lt;h3&gt;
  
  
  Stronger Title After Testing
&lt;/h3&gt;

&lt;p&gt;Self-Hosting Odoo 19 on Oracle OCI Free Tier — Complete Tested Setup Guide&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Why OCI Always Free is interesting for Odoo&lt;/li&gt;
&lt;li&gt;Free-tier limits and what to verify before relying on it&lt;/li&gt;
&lt;li&gt;Create ARM VM&lt;/li&gt;
&lt;li&gt;Configure SSH access&lt;/li&gt;
&lt;li&gt;Open firewall ports&lt;/li&gt;
&lt;li&gt;Install Docker and Docker Compose&lt;/li&gt;
&lt;li&gt;Deploy PostgreSQL + Odoo with Docker Compose&lt;/li&gt;
&lt;li&gt;Configure Nginx reverse proxy&lt;/li&gt;
&lt;li&gt;Add SSL with Let's Encrypt&lt;/li&gt;
&lt;li&gt;First Odoo login and database setup&lt;/li&gt;
&lt;li&gt;Common errors and fixes&lt;/li&gt;
&lt;li&gt;Final architecture diagram&lt;/li&gt;
&lt;li&gt;Link to omni-odoo-stack repo&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Publish Status
&lt;/h3&gt;

&lt;p&gt;Hold until runtime tested.&lt;/p&gt;




&lt;h2&gt;
  
  
  Post 5
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Title
&lt;/h3&gt;

&lt;p&gt;5 Odoo Backend Problems I Fix Every Week And the Code That Solves Them&lt;/p&gt;

&lt;h3&gt;
  
  
  Tags
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;odoo&lt;/code&gt;, &lt;code&gt;python&lt;/code&gt;, &lt;code&gt;postgresql&lt;/code&gt;, &lt;code&gt;backend&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hook
&lt;/h3&gt;

&lt;p&gt;These five problems account for most Odoo backend issues I see in real projects.&lt;/p&gt;

&lt;p&gt;Here is the symptom, the root cause, and the code pattern that fixes each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Can Perform Well
&lt;/h3&gt;

&lt;p&gt;This is search-friendly and practical.&lt;/p&gt;

&lt;p&gt;Developers search for specific Odoo issues, not general strategy.&lt;/p&gt;

&lt;p&gt;Listicles with code also perform well because readers can scan quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structure
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Problem 1 — Slow Scheduled Actions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Scheduled action times out on large datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;The job searches too many records at once and processes everything in a single transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sale.order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;records&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sale.order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;draft&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Always filter and batch scheduled jobs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 2 — Duplicate Records from Webhooks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Every webhook creates duplicate CRM leads, invoices, or messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;No idempotency check.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;omni.whatsapp.message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;external_message_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;duplicate_skipped&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;omni.whatsapp.message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Every external webhook should have a deduplication key.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 3 — Slow Search Views
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Odoo list view takes several seconds to load.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;Frequently filtered fields are not indexed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;partner_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Many2one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;res.partner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Customer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Index fields used in domains, filters, and joins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 4 — Custom Module Breaks on Upgrade
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Module works in one Odoo version but fails after upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;Private/internal methods are used instead of stable ORM patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_some_private_method&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;state&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;Avoid private methods unless there is no alternative.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 5 — n8n + Odoo Authentication Fails
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;n8n returns 401 errors when calling custom Odoo controllers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root Cause
&lt;/h3&gt;

&lt;p&gt;The built-in Odoo node uses JSON-RPC patterns, but custom REST controllers often need explicit HTTP authentication/session handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Pattern
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Authenticate against Odoo
2. Store session cookie
3. Call custom endpoint with cookie/header
4. Handle errors explicitly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lesson
&lt;/h3&gt;

&lt;p&gt;For custom controllers, HTTP Request nodes often give more control than the built-in Odoo node.&lt;/p&gt;




&lt;h2&gt;
  
  
  Suggested Ending
&lt;/h2&gt;

&lt;p&gt;Backend issues in Odoo are rarely solved by adding more automation.&lt;/p&gt;

&lt;p&gt;They are solved by better architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;batching&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;idempotency&lt;/li&gt;
&lt;li&gt;indexing&lt;/li&gt;
&lt;li&gt;clean ORM usage&lt;/li&gt;
&lt;li&gt;proper API boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use these same patterns in my open-source Odoo automation repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;https://github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>fastapi</category>
      <category>erp</category>
    </item>
    <item>
      <title>I Replaced a $300/month Automation Stack with n8n, FastAPI, and Docker</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:52:43 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-replaced-a-300month-automation-stack-with-n8n-fastapi-and-docker-58oj</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-replaced-a-300month-automation-stack-with-n8n-fastapi-and-docker-58oj</guid>
      <description>&lt;p&gt;Most small business automation stacks start simple.&lt;/p&gt;

&lt;p&gt;A form submission goes into a CRM.&lt;/p&gt;

&lt;p&gt;A lead gets scored.&lt;/p&gt;

&lt;p&gt;An email or WhatsApp message gets sent.&lt;/p&gt;

&lt;p&gt;Maybe an invoice gets extracted with AI.&lt;/p&gt;

&lt;p&gt;Then one day, the stack looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Zapier Professional&lt;/td&gt;
&lt;td&gt;$49&lt;/td&gt;
&lt;td&gt;Workflow automation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Make Core&lt;/td&gt;
&lt;td&gt;$29&lt;/td&gt;
&lt;td&gt;Secondary automation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI API&lt;/td&gt;
&lt;td&gt;$60+&lt;/td&gt;
&lt;td&gt;AI processing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HubSpot Starter&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;CRM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typeform&lt;/td&gt;
&lt;td&gt;$25&lt;/td&gt;
&lt;td&gt;Form intake&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airtable Plus&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;Data storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook testing / API tools&lt;/td&gt;
&lt;td&gt;$20+&lt;/td&gt;
&lt;td&gt;Debugging and routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra automation tools&lt;/td&gt;
&lt;td&gt;$30+&lt;/td&gt;
&lt;td&gt;Glue logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$280–$300+/month&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fragmented automation stack&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The bigger problem is not only the cost.&lt;/p&gt;

&lt;p&gt;The bigger problem is fragmentation.&lt;/p&gt;

&lt;p&gt;Zapier triggers Make.&lt;/p&gt;

&lt;p&gt;Make calls an AI API.&lt;/p&gt;

&lt;p&gt;The AI response gets written to Airtable.&lt;/p&gt;

&lt;p&gt;A separate sync pushes data into the CRM.&lt;/p&gt;

&lt;p&gt;Errors happen silently.&lt;/p&gt;

&lt;p&gt;Duplicate records appear.&lt;/p&gt;

&lt;p&gt;Nobody knows where the source of truth lives.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;omni-odoo-stack&lt;/strong&gt; to explore a cleaner alternative:&lt;/p&gt;

&lt;p&gt;A self-hosted, open-source-friendly automation architecture using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;Odoo 19 Community&lt;/li&gt;
&lt;li&gt;Groq / Llama 3&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was to show how a business automation stack can be designed with fewer moving parts, better validation, and lower infrastructure cost.&lt;/p&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Replacement Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Paid / Fragmented Tool&lt;/th&gt;
&lt;th&gt;Replacement&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Zapier / Make / Pipedream&lt;/td&gt;
&lt;td&gt;n8n self-hosted&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raw AI API calls&lt;/td&gt;
&lt;td&gt;FastAPI + Pydantic validation&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HubSpot CRM&lt;/td&gt;
&lt;td&gt;Odoo 19 Community CRM&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airtable&lt;/td&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typeform&lt;/td&gt;
&lt;td&gt;Custom webhook endpoint&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook testing tools&lt;/td&gt;
&lt;td&gt;n8n webhook trigger + logs&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPS hosting&lt;/td&gt;
&lt;td&gt;Oracle OCI Always Free path&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The architecture is designed to run on a single Docker Compose stack.&lt;/p&gt;

&lt;p&gt;The exact cloud cost depends on provider limits and usage, but the project is designed around a &lt;strong&gt;$0/month infrastructure path&lt;/strong&gt; using open-source and free-tier-friendly components.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;At a high level, the system looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inbound trigger
Webhook / form / WhatsApp / API
        ↓
n8n
Workflow orchestration
        ↓
FastAPI middleware
AI processing + validation
        ↓
Groq / Llama 3
LLM intelligence layer
        ↓
PostgreSQL
Data layer
        ↓
Odoo 19 Community
CRM, accounting, inventory, HR
        ↓
Outbound action
WhatsApp reply / email / record update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important design decision is separation.&lt;/p&gt;

&lt;p&gt;n8n handles orchestration.&lt;/p&gt;

&lt;p&gt;FastAPI handles AI and validation.&lt;/p&gt;

&lt;p&gt;Odoo handles ERP records.&lt;/p&gt;

&lt;p&gt;PostgreSQL stores the data.&lt;/p&gt;

&lt;p&gt;WhatsApp handles communication.&lt;/p&gt;

&lt;p&gt;No single tool is forced to do everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why n8n Beats Zapier and Make for Technical Users
&lt;/h2&gt;

&lt;p&gt;Zapier and Make are excellent products.&lt;/p&gt;

&lt;p&gt;If you are non-technical and need something running quickly, they are useful.&lt;/p&gt;

&lt;p&gt;But for developers, agencies, and technical teams, self-hosted n8n gives more control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 1: Per-Execution Pricing Adds Up
&lt;/h2&gt;

&lt;p&gt;Zapier charges by tasks.&lt;/p&gt;

&lt;p&gt;Make charges by operations.&lt;/p&gt;

&lt;p&gt;That works for small flows.&lt;/p&gt;

&lt;p&gt;But once you start processing thousands of records, invoices, leads, or messages, pricing can grow quickly.&lt;/p&gt;

&lt;p&gt;Self-hosted n8n removes per-execution platform pricing.&lt;/p&gt;

&lt;p&gt;You still pay for server resources, API calls, and external services, but the workflow engine itself is under your control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 2: Error Handling Needs to Be First-Class
&lt;/h2&gt;

&lt;p&gt;In real workflows, things fail.&lt;/p&gt;

&lt;p&gt;APIs timeout.&lt;/p&gt;

&lt;p&gt;AI returns malformed JSON.&lt;/p&gt;

&lt;p&gt;A CRM rejects a payload.&lt;/p&gt;

&lt;p&gt;A webhook gets sent twice.&lt;/p&gt;

&lt;p&gt;A database write fails.&lt;/p&gt;

&lt;p&gt;A production workflow needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;retries&lt;/li&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;logging&lt;/li&gt;
&lt;li&gt;duplicate prevention&lt;/li&gt;
&lt;li&gt;alerting&lt;/li&gt;
&lt;li&gt;fallback paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;n8n gives you enough flexibility to route failures into dedicated error workflows, log them, and notify the right person.&lt;/p&gt;

&lt;p&gt;That matters more than people think.&lt;/p&gt;




&lt;h2&gt;
  
  
  Problem 3: Your Data Flow Should Be Understandable
&lt;/h2&gt;

&lt;p&gt;In many automation stacks, the logic is spread across five tools.&lt;/p&gt;

&lt;p&gt;One part lives in Zapier.&lt;/p&gt;

&lt;p&gt;Another part lives in Make.&lt;/p&gt;

&lt;p&gt;Another part lives in Airtable.&lt;/p&gt;

&lt;p&gt;Another part lives inside the CRM.&lt;/p&gt;

&lt;p&gt;Another part lives in an AI prompt.&lt;/p&gt;

&lt;p&gt;When something breaks, debugging becomes painful.&lt;/p&gt;

&lt;p&gt;A self-hosted stack lets you keep the workflow, API layer, database, and ERP integration closer together.&lt;/p&gt;

&lt;p&gt;That makes the system easier to reason about.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why FastAPI Instead of Calling AI Directly from n8n
&lt;/h2&gt;

&lt;p&gt;The biggest mistake I see in AI automation stacks is this:&lt;/p&gt;

&lt;p&gt;Call an LLM directly from a workflow tool and write the raw response into a business system.&lt;/p&gt;

&lt;p&gt;That is dangerous.&lt;/p&gt;

&lt;p&gt;Example of what not to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dangerous pattern
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM can return anything.&lt;/p&gt;

&lt;p&gt;Wrong fields.&lt;/p&gt;

&lt;p&gt;Wrong format.&lt;/p&gt;

&lt;p&gt;Wrong amounts.&lt;/p&gt;

&lt;p&gt;Wrong dates.&lt;/p&gt;

&lt;p&gt;Invalid JSON.&lt;/p&gt;

&lt;p&gt;Hallucinated values.&lt;/p&gt;

&lt;p&gt;If that response goes directly into a CRM, ERP, or accounting system, you are asking for corrupted business data.&lt;/p&gt;

&lt;p&gt;So I added a FastAPI middleware layer between the workflow and the AI model.&lt;/p&gt;

&lt;p&gt;The middleware validates AI output before anything touches Odoo or PostgreSQL.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pydantic Validation Layer
&lt;/h2&gt;

&lt;p&gt;Here is a simplified example using Pydantic v2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;next_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
    &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the AI response does not match the schema, the middleware rejects it.&lt;/p&gt;

&lt;p&gt;That means bad data never reaches the ERP.&lt;/p&gt;




&lt;h2&gt;
  
  
  FastAPI Endpoint Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/analyze/lead&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;analyze_lead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lead&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;(...)):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;x_api_key&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;API_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid API key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3-8b-8192&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyze this lead and respond only with valid JSON &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matching this schema: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_json_schema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Lead data: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;lead&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;response_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json_object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;422&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the safety layer.&lt;/p&gt;

&lt;p&gt;n8n calls FastAPI.&lt;/p&gt;

&lt;p&gt;FastAPI calls the AI model.&lt;/p&gt;

&lt;p&gt;Pydantic validates the response.&lt;/p&gt;

&lt;p&gt;Only validated data is returned to the workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Compose Setup
&lt;/h2&gt;

&lt;p&gt;One Docker Compose file can run the core stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_DB}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;odoo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;odoo:19&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;
      &lt;span class="na"&gt;USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_USER}&lt;/span&gt;
      &lt;span class="na"&gt;PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${POSTGRES_PASSWORD}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;odoo_data:/var/lib/odoo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./odoo/addons:/mnt/extra-addons&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./odoo/config/odoo.conf:/etc/odoo/odoo.conf&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;ai-middleware&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./ai&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GROQ_API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${GROQ_API_KEY}&lt;/span&gt;
      &lt;span class="na"&gt;API_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${AI_API_KEY}&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;n8n&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;n8nio/n8n&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;N8N_BASIC_AUTH_ACTIVE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;N8N_BASIC_AUTH_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${N8N_BASIC_AUTH_USER}&lt;/span&gt;
      &lt;span class="na"&gt;N8N_BASIC_AUTH_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${N8N_BASIC_AUTH_PASSWORD}&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n_data:/home/node/.n8n&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:alpine&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx/nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;odoo&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;n8n&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-middleware&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;omni_net&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;odoo_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;n8n_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;omni_net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Startup flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env

&lt;span class="c"&gt;# Fill in your environment variables&lt;/span&gt;

docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four main services.&lt;/p&gt;

&lt;p&gt;One network.&lt;/p&gt;

&lt;p&gt;One command.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 1: Lead Intake
&lt;/h2&gt;

&lt;p&gt;This replaces a typical form + automation + CRM workflow.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WhatsApp message / web form submission
        ↓
n8n webhook trigger
        ↓
HTTP Request → POST /analyze/lead
        ↓
Validate AI response
        ↓
HTTP Request → POST /api/omni/lead
        ↓
Create Odoo CRM lead
        ↓
Send WhatsApp confirmation
        ↓
Log automation event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Old pattern:&lt;/p&gt;

&lt;p&gt;Form tool → Zapier → AI API → HubSpot → notification&lt;/p&gt;

&lt;p&gt;New pattern:&lt;/p&gt;

&lt;p&gt;Webhook → n8n → FastAPI → Odoo → WhatsApp&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 2: Invoice Processing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invoice text or payload arrives
        ↓
n8n webhook trigger
        ↓
HTTP Request → POST /extract/invoice
        ↓
Pydantic validation
        ↓
Create vendor bill in Odoo
        ↓
Send confirmation
        ↓
Log validation failures if needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key point is not AI extraction.&lt;/p&gt;

&lt;p&gt;The key point is validated AI extraction.&lt;/p&gt;

&lt;p&gt;A malformed invoice should never become an accounting record.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 3: HR Onboarding
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New employee form submitted
        ↓
n8n webhook trigger
        ↓
Create employee in Odoo HR
        ↓
Generate welcome message through FastAPI
        ↓
Send WhatsApp welcome message
        ↓
Notify HR manager
        ↓
Log onboarding event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows that the same stack can support sales, finance, and HR workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Error Handling Pattern
&lt;/h2&gt;

&lt;p&gt;The single biggest problem with many automation stacks is silent failure.&lt;/p&gt;

&lt;p&gt;A workflow fails.&lt;/p&gt;

&lt;p&gt;Nobody notices.&lt;/p&gt;

&lt;p&gt;Leads disappear.&lt;/p&gt;

&lt;p&gt;Invoices are not processed.&lt;/p&gt;

&lt;p&gt;Customers never get replies.&lt;/p&gt;

&lt;p&gt;Every serious workflow should have an error path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Every important workflow step
        ↓
Success path → continue normally
        ↓
Error path → log failure
           → notify admin
           → stop workflow safely
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this stack, failures can be logged into Odoo using &lt;code&gt;omni.automation.log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;They can also trigger WhatsApp or email alerts.&lt;/p&gt;

&lt;p&gt;That gives the business visibility into what failed and why.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five Gotchas That Will Save You Hours
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. n8n's Odoo Node Is Not Enough for Every Case
&lt;/h2&gt;

&lt;p&gt;The built-in Odoo node is useful for standard operations.&lt;/p&gt;

&lt;p&gt;But for custom Odoo REST controllers, HTTP Request nodes are often better.&lt;/p&gt;

&lt;p&gt;They give you more control over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;headers&lt;/li&gt;
&lt;li&gt;custom endpoints&lt;/li&gt;
&lt;li&gt;error responses&lt;/li&gt;
&lt;li&gt;payload shape&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Webhook Idempotency Is Not Optional
&lt;/h2&gt;

&lt;p&gt;Webhook providers may retry failed events.&lt;/p&gt;

&lt;p&gt;If you do not check for duplicate message IDs or event IDs, you can create duplicate records.&lt;/p&gt;

&lt;p&gt;For lead intake, that means duplicate CRM leads.&lt;/p&gt;

&lt;p&gt;For accounting, that could mean duplicate bills.&lt;/p&gt;

&lt;p&gt;Always store an external event ID and check it before creating new records.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. AI Rate Limits Need Workflow Design
&lt;/h2&gt;

&lt;p&gt;Free-tier AI APIs can have rate limits.&lt;/p&gt;

&lt;p&gt;Do not assume every request will succeed immediately.&lt;/p&gt;

&lt;p&gt;For high-volume workflows, add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wait nodes&lt;/li&gt;
&lt;li&gt;retries&lt;/li&gt;
&lt;li&gt;backoff&lt;/li&gt;
&lt;li&gt;failure logging&lt;/li&gt;
&lt;li&gt;fallback behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rate limits should be treated as part of the architecture, not as an afterthought.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Odoo Filestore Persistence Is Easy to Miss
&lt;/h2&gt;

&lt;p&gt;Odoo stores attachments in its filestore.&lt;/p&gt;

&lt;p&gt;If you do not mount the filestore properly in Docker, files can disappear when containers are recreated.&lt;/p&gt;

&lt;p&gt;Use named volumes for persistence.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Docker Services Should Talk by Service Name
&lt;/h2&gt;

&lt;p&gt;Inside a Docker Compose network, services should not call each other using &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Use service names instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://odoo:8069
http://ai-middleware:8000
http://n8n:5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;localhost&lt;/code&gt; points to the current container, not another service.&lt;/p&gt;

&lt;p&gt;This causes many avoidable connection errors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Before and After
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Monthly platform cost&lt;/td&gt;
&lt;td&gt;Around $300&lt;/td&gt;
&lt;td&gt;Designed for $0/month infrastructure path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Services to maintain&lt;/td&gt;
&lt;td&gt;Many separate tools&lt;/td&gt;
&lt;td&gt;One Docker Compose stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflow ownership&lt;/td&gt;
&lt;td&gt;Spread across vendors&lt;/td&gt;
&lt;td&gt;Self-hosted orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error visibility&lt;/td&gt;
&lt;td&gt;Often limited&lt;/td&gt;
&lt;td&gt;Central logs and alerts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data model&lt;/td&gt;
&lt;td&gt;Fragmented&lt;/td&gt;
&lt;td&gt;PostgreSQL + Odoo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI safety&lt;/td&gt;
&lt;td&gt;Raw responses&lt;/td&gt;
&lt;td&gt;Pydantic validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vendor lock-in&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Important note:&lt;/p&gt;

&lt;p&gt;This does not mean there are no external services.&lt;/p&gt;

&lt;p&gt;WhatsApp Cloud API and Groq are still external APIs.&lt;/p&gt;

&lt;p&gt;The difference is that the workflow engine, database, ERP, middleware, and deployment structure are controlled by you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Repository
&lt;/h2&gt;

&lt;p&gt;Everything is open source and available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repo includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose setup&lt;/li&gt;
&lt;li&gt;Odoo configuration&lt;/li&gt;
&lt;li&gt;Custom Odoo modules&lt;/li&gt;
&lt;li&gt;FastAPI middleware&lt;/li&gt;
&lt;li&gt;Pydantic v2 validators&lt;/li&gt;
&lt;li&gt;Importable n8n workflow JSON files&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Setup notes&lt;/li&gt;
&lt;li&gt;Architecture notes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The point of this project is not just to replace paid tools.&lt;/p&gt;

&lt;p&gt;The point is to show that business automation needs real backend architecture.&lt;/p&gt;

&lt;p&gt;A good automation stack needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;validation&lt;/li&gt;
&lt;li&gt;observability&lt;/li&gt;
&lt;li&gt;retry handling&lt;/li&gt;
&lt;li&gt;duplicate prevention&lt;/li&gt;
&lt;li&gt;API boundaries&lt;/li&gt;
&lt;li&gt;secure configuration&lt;/li&gt;
&lt;li&gt;persistent storage&lt;/li&gt;
&lt;li&gt;clean deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is what turns a demo workflow into something a business can actually rely on.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I am a backend engineer specializing in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo ERP customization&lt;/li&gt;
&lt;li&gt;n8n workflow automation&lt;/li&gt;
&lt;li&gt;Python backend systems&lt;/li&gt;
&lt;li&gt;FastAPI middleware&lt;/li&gt;
&lt;li&gt;PostgreSQL optimization&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API integration&lt;/li&gt;
&lt;li&gt;AI middleware with structured output validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have 8+ years of production experience across Odoo, Python, backend automation, and ERP integrations.&lt;/p&gt;

&lt;p&gt;I am open to remote contract work involving Odoo modules, n8n automation, AI middleware, PostgreSQL optimization, and backend integrations.&lt;/p&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;github.com/gharisj3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>n8nbrightdatachallenge</category>
      <category>docker</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I Built a Production-Grade Odoo 19 + n8n + WhatsApp + Groq AI Stack on $0 Infrastructure</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Wed, 10 Jun 2026 20:43:03 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/how-i-built-a-production-grade-odoo-19-n8n-whatsapp-groq-ai-stack-on-0-infrastructure-8kd</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/how-i-built-a-production-grade-odoo-19-n8n-whatsapp-groq-ai-stack-on-0-infrastructure-8kd</guid>
      <description>&lt;p&gt;If you've ever tried to connect an ERP system to real-time messaging, AI processing, and workflow automation at the same time, you know how quickly the architecture can become messy.&lt;/p&gt;

&lt;p&gt;If you've ever tried to connect an ERP system to real-time messaging, AI processing, and workflow automation at the same time, you know how quickly the architecture can become messy.&lt;/p&gt;

&lt;p&gt;You need an ERP.&lt;/p&gt;

&lt;p&gt;You need automation.&lt;/p&gt;

&lt;p&gt;You need message intake.&lt;/p&gt;

&lt;p&gt;You need AI processing.&lt;/p&gt;

&lt;p&gt;You need validation.&lt;/p&gt;

&lt;p&gt;You need logs.&lt;/p&gt;

&lt;p&gt;You need deployment.&lt;/p&gt;

&lt;p&gt;And very quickly, what started as “just connect WhatsApp to Odoo” becomes a full backend system.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;omni-odoo-stack&lt;/strong&gt; to explore that exact problem.&lt;/p&gt;

&lt;p&gt;It is an open-source ERP automation stack built around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo 19 Community&lt;/li&gt;
&lt;li&gt;PostgreSQL 16&lt;/li&gt;
&lt;li&gt;n8n&lt;/li&gt;
&lt;li&gt;FastAPI&lt;/li&gt;
&lt;li&gt;Groq / Llama 3&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;Oracle OCI Always Free deployment path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal was simple:&lt;/p&gt;

&lt;p&gt;Build a realistic &lt;strong&gt;ERP + automation + AI middleware&lt;/strong&gt; architecture using open-source or free-tier-friendly tools.&lt;/p&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Stack Does
&lt;/h2&gt;

&lt;p&gt;At a high level, the system connects five layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WhatsApp Cloud API
        ↓
n8n workflow orchestration
        ↓
FastAPI + Groq AI middleware
        ↓
Odoo 19 Community
        ↓
PostgreSQL 16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a WhatsApp message arrives, n8n receives the webhook, extracts the payload, sends the data to FastAPI for AI-assisted analysis, validates the structured response using Pydantic v2, and writes a clean CRM lead into Odoo.&lt;/p&gt;

&lt;p&gt;The sender can then receive an automated WhatsApp confirmation.&lt;/p&gt;

&lt;p&gt;The important part is not just that the flow works conceptually.&lt;/p&gt;

&lt;p&gt;The important part is the separation of responsibilities.&lt;/p&gt;

&lt;p&gt;Odoo remains the ERP core.&lt;/p&gt;

&lt;p&gt;n8n handles workflow orchestration.&lt;/p&gt;

&lt;p&gt;FastAPI acts as the AI safety boundary.&lt;/p&gt;

&lt;p&gt;PostgreSQL stores the business data.&lt;/p&gt;

&lt;p&gt;WhatsApp handles the communication layer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Infrastructure Stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ERP&lt;/td&gt;
&lt;td&gt;Odoo 19 Community&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;PostgreSQL 16&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;n8n self-hosted&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI middleware&lt;/td&gt;
&lt;td&gt;FastAPI&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM provider&lt;/td&gt;
&lt;td&gt;Groq / Llama 3&lt;/td&gt;
&lt;td&gt;Free-tier friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Messaging&lt;/td&gt;
&lt;td&gt;Meta WhatsApp Cloud API&lt;/td&gt;
&lt;td&gt;Free-tier friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse proxy&lt;/td&gt;
&lt;td&gt;Nginx&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Docker Compose&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting target&lt;/td&gt;
&lt;td&gt;Oracle OCI Always Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSL&lt;/td&gt;
&lt;td&gt;Let's Encrypt&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Oracle OCI Always Free is useful for this kind of project because the ARM instance can provide enough resources for a small ERP automation stack without needing a paid VPS.&lt;/p&gt;

&lt;p&gt;The repo is designed with OCI deployment in mind, but I am being careful with wording here:&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;production-style portfolio architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is not yet being claimed as a fully production-deployed system until the full Docker runtime has been boot-tested on OCI.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Four Custom Odoo Modules
&lt;/h2&gt;

&lt;p&gt;I built four custom Odoo modules from scratch. Each module handles a different part of the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. omni_crm
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_crm&lt;/code&gt; extends &lt;code&gt;crm.lead&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Computed lead scoring&lt;/li&gt;
&lt;li&gt;AI analysis fields&lt;/li&gt;
&lt;li&gt;WhatsApp contact shortcut behavior&lt;/li&gt;
&lt;li&gt;Public lead intake API&lt;/li&gt;
&lt;li&gt;Demo CRM lead data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/omni/lead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This endpoint allows external systems like n8n to create leads in Odoo through a clean REST-style controller instead of forcing all automation through manual imports or UI actions.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. omni_whatsapp
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_whatsapp&lt;/code&gt; introduces a new model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omni.whatsapp.message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It stores WhatsApp message activity inside Odoo.&lt;/p&gt;

&lt;p&gt;Fields include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Phone number&lt;/li&gt;
&lt;li&gt;Message body&lt;/li&gt;
&lt;li&gt;Direction: inbound or outbound&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Linked CRM lead&lt;/li&gt;
&lt;li&gt;Message history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also includes webhook endpoints for Meta WhatsApp Cloud API integration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET  /whatsapp/webhook
POST /whatsapp/webhook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The GET endpoint is used for Meta webhook verification.&lt;/p&gt;

&lt;p&gt;The POST endpoint receives inbound WhatsApp events.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. omni_ai
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_ai&lt;/code&gt; introduces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omni.ai.request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module logs AI requests and responses.&lt;/p&gt;

&lt;p&gt;It stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt&lt;/li&gt;
&lt;li&gt;Response&lt;/li&gt;
&lt;li&gt;Model used&lt;/li&gt;
&lt;li&gt;Token usage&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also includes an hourly cron job to process unanalyzed leads.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;p&gt;Do not let AI calls disappear into the background.&lt;/p&gt;

&lt;p&gt;Every AI action should be visible, inspectable, and traceable inside the ERP.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. omni_automation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;omni_automation&lt;/code&gt; introduces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;omni.automation.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module tracks end-to-end automation events.&lt;/p&gt;

&lt;p&gt;It can be used to monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WhatsApp intake&lt;/li&gt;
&lt;li&gt;CRM lead creation&lt;/li&gt;
&lt;li&gt;AI processing&lt;/li&gt;
&lt;li&gt;Vendor bill automation&lt;/li&gt;
&lt;li&gt;HR onboarding automation&lt;/li&gt;
&lt;li&gt;Failed workflow events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It includes tree, form, and graph views so the automation layer is visible inside Odoo.&lt;/p&gt;

&lt;p&gt;That visibility is important.&lt;/p&gt;

&lt;p&gt;Automation without logs becomes a black box.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the AI Middleware Lives Outside Odoo
&lt;/h2&gt;

&lt;p&gt;This was the most important architectural decision in the project.&lt;/p&gt;

&lt;p&gt;A lot of AI-connected ERP implementations put LLM calls directly inside ERP models or controllers.&lt;/p&gt;

&lt;p&gt;That works for demos, but it creates problems later.&lt;/p&gt;

&lt;p&gt;Problems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts become tightly coupled to Odoo modules&lt;/li&gt;
&lt;li&gt;Model changes require ERP code changes&lt;/li&gt;
&lt;li&gt;Raw LLM responses can accidentally corrupt ERP records&lt;/li&gt;
&lt;li&gt;Validation becomes inconsistent&lt;/li&gt;
&lt;li&gt;Token usage is harder to track&lt;/li&gt;
&lt;li&gt;Swapping models becomes harder than necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I separated the AI layer into a standalone FastAPI service.&lt;/p&gt;

&lt;p&gt;Odoo does not talk directly to the model.&lt;/p&gt;

&lt;p&gt;n8n and Odoo communicate with the middleware.&lt;/p&gt;

&lt;p&gt;The middleware validates input, calls the LLM, validates output, and only then returns structured data.&lt;/p&gt;

&lt;p&gt;Example Pydantic v2 model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LeadAnalysis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;le&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;next_action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example invoice extraction model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LineItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;unit_price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InvoiceData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;date&lt;/span&gt;
    &lt;span class="n"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;line_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LineItem&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every AI response must match the expected schema before it reaches Odoo.&lt;/p&gt;

&lt;p&gt;If the response is missing a field, has the wrong type, or produces an invalid value, the middleware returns an error and the workflow can log the failure.&lt;/p&gt;

&lt;p&gt;Odoo never receives unsafe data.&lt;/p&gt;

&lt;p&gt;That is the entire point of the middleware.&lt;/p&gt;




&lt;h2&gt;
  
  
  FastAPI Middleware Endpoints
&lt;/h2&gt;

&lt;p&gt;The middleware exposes these endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET  /health
POST /analyze/lead
POST /extract/invoice
POST /generate/message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;n8n receives WhatsApp webhook
        ↓
n8n sends payload to FastAPI
        ↓
FastAPI calls Groq / Llama 3
        ↓
Pydantic validates structured output
        ↓
n8n writes validated data into Odoo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The middleware is also easier to evolve independently.&lt;/p&gt;

&lt;p&gt;If I want to replace Groq with OpenAI, Claude, or another model provider, I can change the middleware layer without rewriting Odoo modules.&lt;/p&gt;

&lt;p&gt;That is the benefit of keeping AI outside the ERP core.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three n8n Workflows
&lt;/h2&gt;

&lt;p&gt;The repo includes three importable n8n workflow JSON files.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 1: WhatsApp Lead Intake
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Meta WhatsApp webhook
        ↓
Extract contact and message data
        ↓
Call FastAPI /analyze/lead
        ↓
Validate AI response
        ↓
Create CRM lead in Odoo
        ↓
Send WhatsApp confirmation
        ↓
Log automation event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow is designed for businesses that receive leads through WhatsApp and want automatic CRM creation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 2: Invoice Processing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Invoice payload or WhatsApp invoice text
        ↓
Call FastAPI /extract/invoice
        ↓
Validate structured invoice data
        ↓
Create vendor bill in Odoo
        ↓
Send confirmation
        ↓
Log validation failures if needed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This flow demonstrates how AI extraction can be placed behind validation before data enters accounting workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Workflow 3: HR Onboarding
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Employee onboarding form
        ↓
Create employee in Odoo
        ↓
Generate welcome message through AI middleware
        ↓
Send WhatsApp notification to employee
        ↓
Notify HR manager
        ↓
Log onboarding event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This workflow demonstrates how the same architecture can support HR automation, not just sales or finance.&lt;/p&gt;




&lt;h2&gt;
  
  
  Five Things I Learned While Building This
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. n8n's Odoo Node Is Not Enough for Every Case
&lt;/h2&gt;

&lt;p&gt;The built-in Odoo node in n8n is useful, but custom Odoo REST controllers often require HTTP Request nodes.&lt;/p&gt;

&lt;p&gt;For custom endpoints, the practical pattern is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authenticate with Odoo
Store session/cookie
Call custom REST endpoint
Handle response
Log errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For complex projects, I prefer explicit HTTP Request nodes because they make the flow easier to debug.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. WhatsApp Webhook Idempotency Matters
&lt;/h2&gt;

&lt;p&gt;Messaging systems can resend webhook events.&lt;/p&gt;

&lt;p&gt;If your workflow creates a CRM lead every time it receives the same message, you can end up with duplicate leads.&lt;/p&gt;

&lt;p&gt;The fix is to store and check a unique message identifier before creating records.&lt;/p&gt;

&lt;p&gt;In real projects, I would always design the WhatsApp intake layer with duplicate prevention.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Pydantic v2 Requires Correct Syntax
&lt;/h2&gt;

&lt;p&gt;Pydantic v2 introduced changes from v1.&lt;/p&gt;

&lt;p&gt;If you are using it for AI output validation, make sure your models and validators follow v2 syntax.&lt;/p&gt;

&lt;p&gt;The goal is not just to parse JSON.&lt;/p&gt;

&lt;p&gt;The goal is to reject unsafe or malformed output before it touches business systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Odoo Filestore Persistence Is Easy to Miss
&lt;/h2&gt;

&lt;p&gt;Odoo stores attachments in the filestore.&lt;/p&gt;

&lt;p&gt;If the filestore is not mounted properly in Docker, attachments can disappear when containers are recreated.&lt;/p&gt;

&lt;p&gt;For an ERP system, that is not acceptable.&lt;/p&gt;

&lt;p&gt;Docker volumes need to be planned carefully.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Docker Services Should Talk by Service Name
&lt;/h2&gt;

&lt;p&gt;Inside a Docker Compose network, services should not call each other using &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Wrong:
http://localhost:8069

Correct:
http://odoo:8069
http://ai-middleware:8000
http://n8n:5678
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sounds basic, but it is one of the most common causes of connection errors when wiring multiple services together.&lt;/p&gt;




&lt;h2&gt;
  
  
  Nginx Routing
&lt;/h2&gt;

&lt;p&gt;The stack uses Nginx as the reverse proxy.&lt;/p&gt;

&lt;p&gt;The intended routing is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/       → Odoo
/n8n/   → n8n
/ai/    → FastAPI middleware
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example configuration pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://odoo:8069&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/n8n/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://n8n:5678/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/n8n/(.*)&lt;/span&gt;$ &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/ai/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://ai-middleware:8000/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;rewrite&lt;/span&gt; &lt;span class="s"&gt;^/ai/(.*)&lt;/span&gt;$ &lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="s"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rewrite rules matter because services like n8n and FastAPI may not expect the external prefix in the request path.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Groq and Rate Limits
&lt;/h2&gt;

&lt;p&gt;The project is designed to work with Groq and Llama 3-style structured AI tasks.&lt;/p&gt;

&lt;p&gt;For real deployments, rate limits should always be checked from the current provider dashboard because limits can change.&lt;/p&gt;

&lt;p&gt;In production-style workflows, I would add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wait nodes in n8n&lt;/li&gt;
&lt;li&gt;Retry logic&lt;/li&gt;
&lt;li&gt;Backoff handling&lt;/li&gt;
&lt;li&gt;Token usage logging&lt;/li&gt;
&lt;li&gt;Fallback behavior&lt;/li&gt;
&lt;li&gt;Dead-letter logging for failed events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not just to call an AI model.&lt;/p&gt;

&lt;p&gt;The goal is to make the AI call reliable enough for business workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repository Contents
&lt;/h2&gt;

&lt;p&gt;The repository includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose setup&lt;/li&gt;
&lt;li&gt;Odoo configuration&lt;/li&gt;
&lt;li&gt;Nginx configuration&lt;/li&gt;
&lt;li&gt;Four custom Odoo modules&lt;/li&gt;
&lt;li&gt;FastAPI AI middleware&lt;/li&gt;
&lt;li&gt;Three importable n8n workflows&lt;/li&gt;
&lt;li&gt;Environment example file&lt;/li&gt;
&lt;li&gt;README&lt;/li&gt;
&lt;li&gt;Setup documentation&lt;/li&gt;
&lt;li&gt;Architecture notes&lt;/li&gt;
&lt;li&gt;Phase notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Would Do Differently
&lt;/h2&gt;

&lt;p&gt;One thing I would change is boot-testing the full Docker stack before publishing the first public version.&lt;/p&gt;

&lt;p&gt;The project has been scaffolded, committed, documented, and syntax-checked.&lt;/p&gt;

&lt;p&gt;Python syntax, JSON workflow files, and XML structure were reviewed.&lt;/p&gt;

&lt;p&gt;But full runtime verification on OCI is still pending.&lt;/p&gt;

&lt;p&gt;That is why I describe this as a &lt;strong&gt;production-style architecture&lt;/strong&gt; rather than claiming it is already production-deployed.&lt;/p&gt;

&lt;p&gt;That wording matters.&lt;/p&gt;

&lt;p&gt;If you deploy it and hit issues, open an issue on GitHub. I am happy to improve the repo based on real runtime feedback.&lt;/p&gt;




&lt;h2&gt;
  
  
  Who This Is For
&lt;/h2&gt;

&lt;p&gt;This project is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo developers learning external automation patterns&lt;/li&gt;
&lt;li&gt;n8n users integrating workflows with Odoo&lt;/li&gt;
&lt;li&gt;Backend engineers exploring ERP automation&lt;/li&gt;
&lt;li&gt;Odoo partners evaluating AI middleware architecture&lt;/li&gt;
&lt;li&gt;Agencies that need WhatsApp + ERP workflow examples&lt;/li&gt;
&lt;li&gt;Developers looking for a free-tier-friendly ERP automation stack&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Most ERP automation problems are not just workflow problems.&lt;/p&gt;

&lt;p&gt;They are backend reliability problems.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean data models&lt;/li&gt;
&lt;li&gt;Safe API boundaries&lt;/li&gt;
&lt;li&gt;Structured validation&lt;/li&gt;
&lt;li&gt;Retry handling&lt;/li&gt;
&lt;li&gt;Duplicate prevention&lt;/li&gt;
&lt;li&gt;Event logs&lt;/li&gt;
&lt;li&gt;Database persistence&lt;/li&gt;
&lt;li&gt;Deployment clarity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is what this project is meant to demonstrate.&lt;/p&gt;

&lt;p&gt;Not just that Odoo can connect to AI.&lt;/p&gt;

&lt;p&gt;But that AI, automation, messaging, and ERP can be designed as separate layers that work together cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Me
&lt;/h2&gt;

&lt;p&gt;I am a backend engineer specializing in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Odoo ERP customization&lt;/li&gt;
&lt;li&gt;Python backend systems&lt;/li&gt;
&lt;li&gt;n8n workflow automation&lt;/li&gt;
&lt;li&gt;PostgreSQL optimization&lt;/li&gt;
&lt;li&gt;WhatsApp Cloud API integration&lt;/li&gt;
&lt;li&gt;Claude/OpenAI/Groq AI middleware&lt;/li&gt;
&lt;li&gt;Pydantic-validated structured outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have 8+ years of production experience across Odoo v14–v19 and backend automation work.&lt;/p&gt;

&lt;p&gt;I am open to remote contract work with Odoo partners, SaaS teams, and agencies.&lt;/p&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3" rel="noopener noreferrer"&gt;github.com/gharisj3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LinkedIn:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/muhammad-gharis-javed-318266202/" rel="noopener noreferrer"&gt;linkedin.com/in/muhammad-gharis-javed-318266202&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/gharisj3/omni-odoo-stack" rel="noopener noreferrer"&gt;github.com/gharisj3/omni-odoo-stack&lt;/a&gt;&lt;/p&gt;

</description>
      <category>odoo</category>
      <category>python</category>
      <category>n8nbrightdatachallenge</category>
      <category>docker</category>
    </item>
    <item>
      <title>Anti-Subscription Stack</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Mon, 08 Jun 2026 10:39:38 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/anti-subscription-stack-38dn</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/anti-subscription-stack-38dn</guid>
      <description>&lt;p&gt;Most small businesses do not need another monthly SaaS subscription.&lt;/p&gt;

&lt;p&gt;They need simple software that helps them run daily operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Save customer records&lt;/li&gt;
&lt;li&gt;Track leads&lt;/li&gt;
&lt;li&gt;Create invoices&lt;/li&gt;
&lt;li&gt;Manage inventory&lt;/li&gt;
&lt;li&gt;View sales reports&lt;/li&gt;
&lt;li&gt;Export data when needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is it.&lt;/p&gt;

&lt;p&gt;But somehow, even basic business tools have turned into complicated subscription products with multiple pricing tiers, feature gates, usage limits, and dashboards that small teams never fully use.&lt;/p&gt;

&lt;p&gt;This is why I think there is still a strong place for lightweight, self-hosted tools.&lt;/p&gt;

&lt;p&gt;Especially tools built with simple stacks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core PHP
MySQL
HTML
CSS
JavaScript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No heavy framework.&lt;br&gt;&lt;br&gt;
No paid API.&lt;br&gt;&lt;br&gt;
No complex deployment.&lt;br&gt;&lt;br&gt;
No monthly platform dependency.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem With Overbuilt Business Software
&lt;/h2&gt;

&lt;p&gt;A small shop, freelancer, salon, repair center, consultant, or local agency usually does not need enterprise software.&lt;/p&gt;

&lt;p&gt;They need something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clients
Products
Invoices
Payments
Tasks
Reports
Users
Settings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But many modern tools are built as if every customer is a funded startup with a large operations team.&lt;/p&gt;

&lt;p&gt;The result?&lt;/p&gt;

&lt;p&gt;Small businesses often end up with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many features&lt;/li&gt;
&lt;li&gt;Too many screens&lt;/li&gt;
&lt;li&gt;Too many monthly fees&lt;/li&gt;
&lt;li&gt;Too much onboarding&lt;/li&gt;
&lt;li&gt;Too much vendor lock-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For basic workflows, this is unnecessary.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Self-Hosted Still Matters
&lt;/h2&gt;

&lt;p&gt;Self-hosted software is not dead.&lt;/p&gt;

&lt;p&gt;For many use cases, it is actually practical.&lt;/p&gt;

&lt;p&gt;A small business owner or freelancer may prefer self-hosted tools because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They pay once instead of monthly&lt;/li&gt;
&lt;li&gt;They can keep their own database&lt;/li&gt;
&lt;li&gt;They can customize the system&lt;/li&gt;
&lt;li&gt;They can host it on basic shared hosting&lt;/li&gt;
&lt;li&gt;They are not locked into one vendor&lt;/li&gt;
&lt;li&gt;They can hire any PHP developer to modify it later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially useful for small internal systems.&lt;/p&gt;

&lt;p&gt;A CRM, POS, HRM, invoice system, or reporting dashboard does not always need to be a full SaaS platform.&lt;/p&gt;

&lt;p&gt;Sometimes a simple admin panel is enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Still Like Core PHP for These Tools
&lt;/h2&gt;

&lt;p&gt;Core PHP gets criticized a lot.&lt;/p&gt;

&lt;p&gt;Sometimes fairly.&lt;/p&gt;

&lt;p&gt;But for small business tools, it still has advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs almost everywhere&lt;/li&gt;
&lt;li&gt;Easy deployment&lt;/li&gt;
&lt;li&gt;Low hosting requirements&lt;/li&gt;
&lt;li&gt;Easy for junior developers to understand&lt;/li&gt;
&lt;li&gt;No complicated build step&lt;/li&gt;
&lt;li&gt;No framework upgrade pressure&lt;/li&gt;
&lt;li&gt;Great for CRUD-heavy systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A clean Core PHP project can still be professional if it uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PDO&lt;/li&gt;
&lt;li&gt;Prepared statements&lt;/li&gt;
&lt;li&gt;Proper validation&lt;/li&gt;
&lt;li&gt;Session security&lt;/li&gt;
&lt;li&gt;Organized folders&lt;/li&gt;
&lt;li&gt;Reusable components&lt;/li&gt;
&lt;li&gt;Clear documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bad PHP is bad.&lt;/p&gt;

&lt;p&gt;But simple PHP is not automatically bad.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: A Lightweight CRM Structure
&lt;/h2&gt;

&lt;p&gt;A simple CRM does not need to start huge.&lt;/p&gt;

&lt;p&gt;It can begin with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crm/
  config/
    database.php

  modules/
    clients/
    leads/
    tasks/
    invoices/

  public/
    index.php
    assets/

  database/
    install.sql

  docs/
    installation.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is enough for a clean first version.&lt;/p&gt;

&lt;p&gt;You can add complexity later only when the business actually needs it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Useful Modules for Small Businesses
&lt;/h2&gt;

&lt;p&gt;If I were building a lightweight business toolkit, I would start with these modules.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Client Management
&lt;/h3&gt;

&lt;p&gt;Store customer details, contact info, notes, and status.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lead Pipeline
&lt;/h3&gt;

&lt;p&gt;Track potential deals from new lead to won or lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Invoice Generator
&lt;/h3&gt;

&lt;p&gt;Create simple invoices with printable HTML templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Inventory Tracking
&lt;/h3&gt;

&lt;p&gt;Useful for shops, repair centers, and small product sellers.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Task Management
&lt;/h3&gt;

&lt;p&gt;Assign daily work and track progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Reports
&lt;/h3&gt;

&lt;p&gt;Show monthly sales, pending invoices, top clients, and stock alerts.&lt;/p&gt;

&lt;p&gt;Nothing fancy.&lt;/p&gt;

&lt;p&gt;Just useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Opportunity for Developers
&lt;/h2&gt;

&lt;p&gt;Many developers are chasing big SaaS ideas.&lt;/p&gt;

&lt;p&gt;But there is a quieter opportunity:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build small, reliable tools that solve boring business problems.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Boring problems pay because businesses already understand them.&lt;/p&gt;

&lt;p&gt;A shop owner does not need to be educated about inventory.&lt;/p&gt;

&lt;p&gt;An agency owner does not need to be convinced about invoices.&lt;/p&gt;

&lt;p&gt;A freelancer already understands client tracking.&lt;/p&gt;

&lt;p&gt;The problem is obvious.&lt;/p&gt;

&lt;p&gt;The solution just needs to be simple and affordable.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Am Building
&lt;/h2&gt;

&lt;p&gt;I am working on a lightweight Core PHP business toolkit starting with a CRM starter system.&lt;/p&gt;

&lt;p&gt;The goal is to make it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to install&lt;/li&gt;
&lt;li&gt;Easy to customize&lt;/li&gt;
&lt;li&gt;Cleanly structured&lt;/li&gt;
&lt;li&gt;Useful for real business workflows&lt;/li&gt;
&lt;li&gt;Suitable for freelancers and small agencies&lt;/li&gt;
&lt;li&gt;Free from heavy framework dependency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am starting small with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Clients
Leads
Tasks
Invoices
Dashboard
Reports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I plan to expand into POS, HRM, and automation modules.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;Not every business tool needs to become a huge SaaS.&lt;/p&gt;

&lt;p&gt;Sometimes the better product is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smaller&lt;/li&gt;
&lt;li&gt;Faster&lt;/li&gt;
&lt;li&gt;Self-hosted&lt;/li&gt;
&lt;li&gt;Easier to understand&lt;/li&gt;
&lt;li&gt;Easier to modify&lt;/li&gt;
&lt;li&gt;Cheaper to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the kind of software I want to build more of.&lt;/p&gt;

&lt;p&gt;If you are a developer, freelancer, or small business owner:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Would you rather use a simple self-hosted tool or pay monthly for a SaaS product with more features than you need?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>saas</category>
      <category>business</category>
    </item>
    <item>
      <title>AI Can Generate Code, But It Still Cannot Understand Your Small Business Workflow</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 07 Jun 2026 16:14:41 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/ai-can-generate-code-but-it-still-cannot-understand-your-small-business-workflow-10d6</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/ai-can-generate-code-but-it-still-cannot-understand-your-small-business-workflow-10d6</guid>
      <description>&lt;p&gt;AI tools can generate code quickly.&lt;/p&gt;

&lt;p&gt;They can create forms, tables, functions, components, and even full project structures.&lt;/p&gt;

&lt;p&gt;But there is one thing they still struggle with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Understanding the real workflow behind a business.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is where developers still matter.&lt;/p&gt;

&lt;p&gt;Especially developers who can turn messy business requirements into simple, working systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Code Is Not the Product
&lt;/h2&gt;

&lt;p&gt;A lot of people think software is just code.&lt;/p&gt;

&lt;p&gt;But business software is not just code.&lt;/p&gt;

&lt;p&gt;Business software is workflow.&lt;/p&gt;

&lt;p&gt;For example, a CRM is not just a &lt;code&gt;clients&lt;/code&gt; table.&lt;/p&gt;

&lt;p&gt;It needs to answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens when a lead becomes a client?&lt;/li&gt;
&lt;li&gt;Who follows up with the customer?&lt;/li&gt;
&lt;li&gt;What status should an invoice have?&lt;/li&gt;
&lt;li&gt;Can a task be linked to a client?&lt;/li&gt;
&lt;li&gt;Should a deleted invoice really be deleted?&lt;/li&gt;
&lt;li&gt;Who can export reports?&lt;/li&gt;
&lt;li&gt;What should appear on the dashboard?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are not just coding questions.&lt;/p&gt;

&lt;p&gt;These are business logic questions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With AI-Generated Admin Panels
&lt;/h2&gt;

&lt;p&gt;AI can generate a basic admin panel very fast.&lt;/p&gt;

&lt;p&gt;But many generated systems have problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inconsistent naming&lt;/li&gt;
&lt;li&gt;Weak validation&lt;/li&gt;
&lt;li&gt;Repeated code&lt;/li&gt;
&lt;li&gt;Poor database structure&lt;/li&gt;
&lt;li&gt;Missing edge cases&lt;/li&gt;
&lt;li&gt;No clear user flow&lt;/li&gt;
&lt;li&gt;No business rules&lt;/li&gt;
&lt;li&gt;No proper documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output may look impressive at first.&lt;/p&gt;

&lt;p&gt;But once a real user starts using it, the gaps appear.&lt;/p&gt;

&lt;p&gt;That is why there is still demand for clean starter kits, boilerplates, and workflow-based systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Small Business Software Needs Practical Thinking
&lt;/h2&gt;

&lt;p&gt;A small business owner does not care if the code was generated by AI, written manually, or built with a framework.&lt;/p&gt;

&lt;p&gt;They care about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I add my customers?
Can I track my sales?
Can I print invoices?
Can I check pending payments?
Can my staff use it?
Can I get reports?
Can it be changed later?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the answer is yes, the system has value.&lt;/p&gt;

&lt;p&gt;If the answer is no, the code does not matter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: CRM Workflow Logic
&lt;/h2&gt;

&lt;p&gt;A basic CRM should not only store leads.&lt;/p&gt;

&lt;p&gt;It should handle simple workflow movement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New Lead
↓
Contacted
↓
Proposal Sent
↓
Won / Lost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage can have rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If lead is marked as Won:
  - Create client record
  - Create first task
  - Show in dashboard
  - Allow invoice creation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the kind of thinking that makes software useful.&lt;/p&gt;

&lt;p&gt;Not just code generation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example: POS Workflow Logic
&lt;/h2&gt;

&lt;p&gt;A POS system is not just products and sales.&lt;/p&gt;

&lt;p&gt;It needs practical rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;When sale is created:
  - Reduce stock
  - Save receipt
  - Update daily sales
  - Record payment method
  - Show low-stock alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, the value is in the workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Lightweight Boilerplates Still Matter
&lt;/h2&gt;

&lt;p&gt;A good boilerplate saves time because it already includes the boring foundation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;CRUD structure&lt;/li&gt;
&lt;li&gt;Dashboard layout&lt;/li&gt;
&lt;li&gt;Database schema&lt;/li&gt;
&lt;li&gt;Reusable components&lt;/li&gt;
&lt;li&gt;Common business modules&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Sample data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives developers a starting point.&lt;/p&gt;

&lt;p&gt;Instead of asking AI to generate random files from scratch every time, a developer can start from a tested structure and customize it.&lt;/p&gt;

&lt;p&gt;That is faster.&lt;/p&gt;

&lt;p&gt;And usually safer.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Current Build Direction
&lt;/h2&gt;

&lt;p&gt;I am building lightweight business starter kits around common workflows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CRM
POS
HRM
Invoicing
Data import/export
CSV automation
Reports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The focus is not on hype.&lt;/p&gt;

&lt;p&gt;The focus is on simple tools that small businesses can actually use.&lt;/p&gt;

&lt;p&gt;My preferred stack for these tools is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Core PHP
MySQL
Vanilla JavaScript
Python automation scripts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because this stack is easy to host, easy to explain, and easy to customize.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Developer Opportunity
&lt;/h2&gt;

&lt;p&gt;AI makes basic code cheaper.&lt;/p&gt;

&lt;p&gt;But it also makes workflow thinking more valuable.&lt;/p&gt;

&lt;p&gt;The opportunity is not just to write code.&lt;/p&gt;

&lt;p&gt;The opportunity is to package solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CRM starter kits&lt;/li&gt;
&lt;li&gt;POS templates&lt;/li&gt;
&lt;li&gt;Invoice generators&lt;/li&gt;
&lt;li&gt;CSV automation scripts&lt;/li&gt;
&lt;li&gt;Admin dashboard modules&lt;/li&gt;
&lt;li&gt;Data cleaning tools&lt;/li&gt;
&lt;li&gt;Migration helpers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are practical products.&lt;/p&gt;

&lt;p&gt;They solve known problems.&lt;/p&gt;

&lt;p&gt;And buyers understand them quickly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;AI can help generate code.&lt;/p&gt;

&lt;p&gt;But business software still needs someone to understand the process, clean the structure, test the flow, and package the solution.&lt;/p&gt;

&lt;p&gt;That is where developers can still win.&lt;/p&gt;

&lt;p&gt;Build boring tools.&lt;/p&gt;

&lt;p&gt;Solve obvious problems.&lt;/p&gt;

&lt;p&gt;Package them clearly.&lt;/p&gt;

&lt;p&gt;That is still a strong path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What small business workflow would you automate first: CRM, POS, invoices, HR, or reporting?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>I Built a Lightweight CRM Starter Kit in Core PHP — No Laravel, No Composer, No Framework Bloat</title>
      <dc:creator>Muhammad Gharis</dc:creator>
      <pubDate>Sun, 07 Jun 2026 16:01:37 +0000</pubDate>
      <link>https://dev.to/muhammad_gharis_fe079470a/i-built-a-lightweight-crm-starter-kit-in-core-php-no-laravel-no-composer-no-framework-bloat-3n3</link>
      <guid>https://dev.to/muhammad_gharis_fe079470a/i-built-a-lightweight-crm-starter-kit-in-core-php-no-laravel-no-composer-no-framework-bloat-3n3</guid>
      <description>&lt;p&gt;Most small business software does not need a heavy framework.&lt;/p&gt;

&lt;p&gt;A freelancer, small agency, repair shop, salon, or local service business usually needs something simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add clients&lt;/li&gt;
&lt;li&gt;Track leads&lt;/li&gt;
&lt;li&gt;Manage tasks&lt;/li&gt;
&lt;li&gt;Create invoices&lt;/li&gt;
&lt;li&gt;View basic reports&lt;/li&gt;
&lt;li&gt;Export data&lt;/li&gt;
&lt;li&gt;Run everything on basic shared hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is why I started building a lightweight Core PHP CRM Starter Kit.&lt;/p&gt;

&lt;p&gt;The goal is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build a clean, fast, self-hosted CRM foundation that developers can understand, customize, and deploy without fighting a huge framework.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why Core PHP?
&lt;/h2&gt;

&lt;p&gt;Frameworks are powerful, but not every project needs one.&lt;/p&gt;

&lt;p&gt;For many small CRM, HRM, POS, and admin panel projects, Core PHP still makes a lot of sense because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It runs on almost any shared hosting&lt;/li&gt;
&lt;li&gt;There is no complex setup&lt;/li&gt;
&lt;li&gt;No Composer dependency required&lt;/li&gt;
&lt;li&gt;Easy for beginners and junior developers to understand&lt;/li&gt;
&lt;li&gt;Fast enough for small and medium business workflows&lt;/li&gt;
&lt;li&gt;Easy to customize for local clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A lot of small business clients do not care whether the system uses the latest framework.&lt;/p&gt;

&lt;p&gt;They care about this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does it work?&lt;br&gt;
Is it fast?&lt;br&gt;
Can I manage my business from it?&lt;br&gt;
Can it be customized without a huge monthly bill?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What I Am Building
&lt;/h2&gt;

&lt;p&gt;The first version of the CRM includes the core modules most small businesses need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client Management&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Basic client records with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Email&lt;/li&gt;
&lt;li&gt;Phone&lt;/li&gt;
&lt;li&gt;Company&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Notes&lt;/li&gt;
&lt;li&gt;Lead Pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple lead tracking system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New lead&lt;/li&gt;
&lt;li&gt;Contacted&lt;/li&gt;
&lt;li&gt;Proposal sent&lt;/li&gt;
&lt;li&gt;Won&lt;/li&gt;
&lt;li&gt;Lost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing overcomplicated. Just a practical sales pipeline.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Task Management&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A basic task module for daily work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Task title&lt;/li&gt;
&lt;li&gt;Related client&lt;/li&gt;
&lt;li&gt;Due date&lt;/li&gt;
&lt;li&gt;Priority&lt;/li&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Invoice Module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple invoice system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invoice number&lt;/li&gt;
&lt;li&gt;Client&lt;/li&gt;
&lt;li&gt;Items&lt;/li&gt;
&lt;li&gt;Quantity&lt;/li&gt;
&lt;li&gt;Price&lt;/li&gt;
&lt;li&gt;Total
Print-friendly invoice page&lt;/li&gt;
&lt;li&gt;Dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The dashboard shows useful numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total clients&lt;/li&gt;
&lt;li&gt;Open leads&lt;/li&gt;
&lt;li&gt;Pending tasks&lt;/li&gt;
&lt;li&gt;Monthly invoice total&lt;/li&gt;
&lt;li&gt;Planned Folder Structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the simple structure I am using:&lt;/p&gt;

&lt;p&gt;leancrm-core/&lt;br&gt;
  app/&lt;br&gt;
    config/&lt;br&gt;
      database.php&lt;br&gt;
    controllers/&lt;br&gt;
      ClientController.php&lt;br&gt;
      LeadController.php&lt;br&gt;
      TaskController.php&lt;br&gt;
      InvoiceController.php&lt;br&gt;
    models/&lt;br&gt;
      Client.php&lt;br&gt;
      Lead.php&lt;br&gt;
      Task.php&lt;br&gt;
      Invoice.php&lt;br&gt;
    views/&lt;br&gt;
      clients/&lt;br&gt;
      leads/&lt;br&gt;
      tasks/&lt;br&gt;
      invoices/&lt;br&gt;
      dashboard.php&lt;br&gt;
    helpers/&lt;br&gt;
      auth.php&lt;br&gt;
      functions.php&lt;/p&gt;

&lt;p&gt;public/&lt;br&gt;
    assets/&lt;br&gt;
      css/&lt;br&gt;
      js/&lt;br&gt;
    index.php&lt;/p&gt;

&lt;p&gt;database/&lt;br&gt;
    install.sql&lt;br&gt;
    sample_data.sql&lt;/p&gt;

&lt;p&gt;docs/&lt;br&gt;
    installation.md&lt;br&gt;
    customization.md&lt;/p&gt;

&lt;p&gt;README.md&lt;/p&gt;

&lt;p&gt;The idea is to keep everything easy to follow.&lt;/p&gt;

&lt;p&gt;No hidden magic.&lt;br&gt;
No huge dependency tree.&lt;br&gt;
No complicated build process.&lt;/p&gt;

&lt;p&gt;Example Database Table&lt;/p&gt;

&lt;p&gt;A simple clients table can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;phone&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;company&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'active'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;notes&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="nb"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a starter CRM, this is enough.&lt;/p&gt;

&lt;p&gt;You can always extend it later with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tags&lt;/li&gt;
&lt;li&gt;Custom fields&lt;/li&gt;
&lt;li&gt;Client categories&lt;/li&gt;
&lt;li&gt;Assigned users&lt;/li&gt;
&lt;li&gt;Activity history
Example PHP Database Connection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am keeping the database connection simple using PDO:&lt;/p&gt;

&lt;p&gt;`&amp;lt;?php&lt;/p&gt;

&lt;p&gt;$host = "localhost";&lt;br&gt;
$dbname = "leancrm";&lt;br&gt;
$username = "root";&lt;br&gt;
$password = "";&lt;/p&gt;

&lt;p&gt;try {&lt;br&gt;
    $pdo = new PDO(&lt;br&gt;
        "mysql:host=$host;dbname=$dbname;charset=utf8mb4",&lt;br&gt;
        $username,&lt;br&gt;
        $password&lt;br&gt;
    );&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$pdo-&amp;gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;} catch (PDOException $e) {&lt;br&gt;
    die("Database connection failed.");&lt;br&gt;
}&lt;br&gt;
`&lt;br&gt;
For production, credentials should be stored safely and error messages should not expose sensitive details.&lt;/p&gt;

&lt;p&gt;Why This Could Be Useful&lt;/p&gt;

&lt;p&gt;This type of project can help three kinds of people:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Beginner PHP Developers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They can study a real business application instead of only learning isolated tutorials.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Freelancers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;They can customize the CRM for small clients such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agencies&lt;/li&gt;
&lt;li&gt;Consultants&lt;/li&gt;
&lt;li&gt;Clinics&lt;/li&gt;
&lt;li&gt;Salons&lt;/li&gt;
&lt;li&gt;Repair shops&lt;/li&gt;
&lt;li&gt;Real estate agents&lt;/li&gt;
&lt;li&gt;Training centers&lt;/li&gt;
&lt;li&gt;3. Small Business Owners&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They can use a simple self-hosted system instead of paying monthly SaaS fees for basic workflows.&lt;/p&gt;

&lt;p&gt;What I Am Avoiding&lt;/p&gt;

&lt;p&gt;I am intentionally not adding unnecessary complexity in the first version.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No multi-tenant SaaS.&lt;/li&gt;
&lt;li&gt;No paid APIs.&lt;/li&gt;
&lt;li&gt;No heavy JavaScript framework.&lt;/li&gt;
&lt;li&gt;No complex build tools.&lt;/li&gt;
&lt;li&gt;No over-engineered architecture.
The first version focuses on one thing:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A clean, understandable CRM foundation that works.&lt;/p&gt;

&lt;p&gt;Future Modules&lt;/p&gt;

&lt;p&gt;After the first release, I may add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User roles&lt;/li&gt;
&lt;li&gt;Activity logs&lt;/li&gt;
&lt;li&gt;CSV export&lt;/li&gt;
&lt;li&gt;Payment status tracking&lt;/li&gt;
&lt;li&gt;Quotation module&lt;/li&gt;
&lt;li&gt;Basic reports&lt;/li&gt;
&lt;li&gt;Email templates&lt;/li&gt;
&lt;li&gt;POS module&lt;/li&gt;
&lt;li&gt;HRM module&lt;/li&gt;
&lt;li&gt;Installer wizard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The long-term goal is to create a small ecosystem of lightweight business tools.&lt;/p&gt;

&lt;p&gt;Final Thought&lt;/p&gt;

&lt;p&gt;Not every software project needs to be huge.&lt;/p&gt;

&lt;p&gt;Sometimes the best tool is the one that is:&lt;/p&gt;

&lt;p&gt;Simple&lt;br&gt;
Fast&lt;br&gt;
Easy to deploy&lt;br&gt;
Easy to understand&lt;br&gt;
Easy to customize&lt;/p&gt;

&lt;p&gt;That is the philosophy behind this Core PHP CRM Starter Kit.&lt;/p&gt;

&lt;p&gt;I will keep sharing updates as I build the modules step by step.&lt;/p&gt;

&lt;p&gt;If you are a PHP developer, freelancer, or someone who builds tools for small businesses, I would love to know:&lt;/p&gt;

&lt;p&gt;What module would you add first to a lightweight CRM?&lt;/p&gt;

</description>
      <category>php</category>
      <category>webdev</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
