Go to file
2026-05-21 16:47:37 +07:00
static Initial Commit 2026-05-18 10:39:40 +07:00
templates Update Login Method & Prevent Duplicate Customer Data 2026-05-21 16:47:37 +07:00
.gitignore Initial Commit 2026-05-18 10:39:40 +07:00
app.py Update Login Method & Prevent Duplicate Customer Data 2026-05-21 16:47:37 +07:00
customer-data-rawformat-2604230703365650-1.xlsx Upload Excel Test File 2026-05-18 13:29:11 +07:00
import.py Upload Excel Test File 2026-05-18 13:29:11 +07:00
README.md Update Login Method & Prevent Duplicate Customer Data 2026-05-21 16:47:37 +07:00
requirements.txt Update Login Method & Prevent Duplicate Customer Data 2026-05-21 16:47:37 +07:00

Tada to Odoo 19 Migration Portal

A lightweight, modern web application built with Python (Flask) that streamlines the process of migrating member/customer data from a PostgreSQL database (tada_member) directly into an Odoo 19 instance via XML-RPC.

🚀 Features

  • Direct Odoo Integration: Seamlessly creates or updates res.partner and loyalty.card records in Odoo 19.
  • Smart Duplicate Prevention: Automatically normalizes phone numbers (stripping non-digits and 0 or 62 prefixes) to find existing customers in Odoo. If a customer already exists, it intelligently fills in empty fields without overwriting existing data.
  • Data Accumulation: Accumulates (adds up) values for total_spend and loyalty points if the customer or loyalty card already exists in Odoo, rather than overwriting them.
  • High-Performance DataTables: Uses Server-Side Processing for pagination, sorting, and debounced searching. This ensures the UI remains lightning-fast, even with hundreds of thousands of records.
  • Beautiful & Modern UI: Features a clean, responsive "Glassmorphism" light theme optimized for both Desktop and Mobile environments.
  • Secure MySQL Authentication: Employee logins are handled via a separate MySQL database. Passwords are verified using encoding, with a fallback for a default unencrypted default password.
  • Interactive Prompts: Integrated with SweetAlert2 to prevent accidental migrations and to provide clean success/error feedback.

🛠️ Tech Stack

  • Backend: Python 3, Flask, Flask-Session
  • Databases:
    • psycopg2-binary (PostgreSQL - for Member Data)
    • PyMySQL (MySQL - for Employee Login)
  • Odoo Integration: xmlrpc.client (Odoo XML-RPC API)
  • Frontend: HTML5, CSS3, Vanilla JavaScript, jQuery, DataTables, SweetAlert2

📦 Installation & Setup

  1. Clone or Extract the Repository Ensure you are in the project root directory.

  2. Create a Virtual Environment (Optional but Recommended)

    python -m venv venv
    # On Windows:
    venv\Scripts\activate
    # On macOS/Linux:
    source venv/bin/activate
    
  3. Install Dependencies Install the required Python packages using pip:

    pip install -r requirements.txt
    
  4. Configure Credentials Open app.py in your text editor and locate the Configurations section at the top of the file. Update the placeholders with your actual PostgreSQL, MySQL, and Odoo 19 credentials:

    # PostgreSQL (Member Data)
    DB_HOST = "localhost"
    DB_PORT = "5432"
    DB_NAME = "your_postgres_db"
    DB_USER = "your_postgres_user"
    DB_PASS = "your_postgres_password"
    
    # Odoo 19
    ODOO_URL = "http://localhost:8069"
    ODOO_DB = "odoo19_db"
    ODOO_USER = "admin"
    ODOO_PASS = "admin"
    
    # MySQL (Login DB)
    MYSQL_HOST = "localhost"
    MYSQL_PORT = 3306
    MYSQL_DB = "klaim_db"
    MYSQL_USER = "your_mysql_user"
    MYSQL_PASS = "your_mysql_password"
    
  5. Run the Application

    python app.py
    

    The application will start a local development server. Open your web browser and navigate to: http://localhost:5000

🔄 Data Mapping Reference

When a migration is triggered, the following mapping occurs:

1. res.partner (Customer Profile)

PostgreSQL (tada_member) Odoo 19 (res.partner) Notes
name name
phone_number phone Normalized for searching to prevent duplicates
email email Updates only if Odoo field is empty
gender gender Capitalized automatically (e.g., female -> Female)
birthday birth_date Updates only if Odoo field is empty
city city Updates only if Odoo field is empty
total_spending total_spend Converted to Float. Accumulates if data exists.
level membership_level_id Linked via loyalty.program search (Many2one)

2. loyalty.card (Membership Card)

PostgreSQL (tada_member) Odoo 19 (loyalty.card) Notes
point_amount points Converted to Float. Accumulates if card exists.
(Generated) partner_id Linked to the matched/created res.partner ID
(Generated) program_id Linked to the matched loyalty.program ID

🛡️ Important Notes

  • Data Validation: The script automatically handles NULL/None values from PostgreSQL, safely converting them to False to prevent XML-RPC marshal errors when writing to Odoo.
  • Debounce Optimization: The search bar waits 400ms after you stop typing and requires a minimum of 3 characters before querying the database, drastically reducing server load.
  • Session Expiry: Security sessions automatically expire after 8 hours of inactivity.