192 lines
7.1 KiB
Python
192 lines
7.1 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import odoorpc
|
|
import argparse
|
|
import sys
|
|
from tqdm import tqdm
|
|
|
|
|
|
def parse_arguments():
|
|
parser = argparse.ArgumentParser(
|
|
description="Update contacts to add salesperson and their manager as followers"
|
|
)
|
|
parser.add_argument("--host", required=True, help="Odoo server host")
|
|
parser.add_argument("--port", type=int, default=8069, help="Odoo server port")
|
|
parser.add_argument("--db", required=True, help="Database name")
|
|
parser.add_argument("--user", required=True, help="Username")
|
|
parser.add_argument("--password", required=True, help="Password")
|
|
parser.add_argument(
|
|
"--limit", type=int, help="Limit the number of contacts to process"
|
|
)
|
|
parser.add_argument(
|
|
"--batch-size", type=int, default=100, help="Batch size for processing"
|
|
)
|
|
return parser.parse_args()
|
|
|
|
|
|
def main():
|
|
args = parse_arguments()
|
|
|
|
# Connect to Odoo
|
|
print(f"Connecting to {args.host}:{args.port}, database {args.db}...")
|
|
try:
|
|
odoo = odoorpc.ODOO(args.host, port=args.port)
|
|
odoo.login(args.db, args.user, args.password)
|
|
print("Connected successfully")
|
|
except Exception as e:
|
|
print(f"Connection failed: {e}")
|
|
sys.exit(1)
|
|
|
|
# Get all contacts with salespersons
|
|
contact_domain = [("user_id", "!=", False)]
|
|
|
|
# Get total count
|
|
contact_count = odoo.env["res.partner"].search_count(contact_domain)
|
|
print(f"Found {contact_count} contacts with assigned salespersons")
|
|
|
|
# Apply limit if specified
|
|
if args.limit and args.limit > 0:
|
|
print(f"Processing only {args.limit} contacts due to limit argument")
|
|
contact_count = min(contact_count, args.limit)
|
|
|
|
# Search contacts
|
|
contact_ids = odoo.env["res.partner"].search(contact_domain, limit=args.limit)
|
|
|
|
# Process in batches to avoid memory issues
|
|
batch_size = args.batch_size
|
|
total_updated = 0
|
|
|
|
# Pre-fetch user and employee data
|
|
print("Pre-fetching user and employee data...")
|
|
user_partner_cache = {} # Maps user_id to partner_id
|
|
user_manager_partners_cache = {} # Maps user_id to list of manager partner_ids
|
|
|
|
# Setup progress bar
|
|
total_batches = (len(contact_ids) + batch_size - 1) // batch_size
|
|
pbar = tqdm(total=total_batches, desc="Processing batches")
|
|
|
|
for i in range(0, len(contact_ids), batch_size):
|
|
batch_ids = contact_ids[i : i + batch_size]
|
|
batch_contacts = odoo.env["res.partner"].browse(batch_ids)
|
|
batch_updated = 0
|
|
|
|
# Collect all salesperson IDs in this batch
|
|
salesperson_ids = [
|
|
contact.user_id.id for contact in batch_contacts if contact.user_id
|
|
]
|
|
unique_salesperson_ids = list(set(salesperson_ids))
|
|
|
|
# Bulk fetch salesperson partner IDs if not in cache
|
|
new_user_ids = [
|
|
uid for uid in unique_salesperson_ids if uid not in user_partner_cache
|
|
]
|
|
if new_user_ids:
|
|
users = odoo.env["res.users"].browse(new_user_ids)
|
|
for user in users:
|
|
user_partner_cache[user.id] = user.partner_id.id
|
|
|
|
# Bulk fetch employee data for salespeople not in cache
|
|
new_employee_fetch = [
|
|
uid
|
|
for uid in unique_salesperson_ids
|
|
if uid not in user_manager_partners_cache
|
|
]
|
|
if new_employee_fetch:
|
|
# Find employee records for these users
|
|
employee_domain = [("user_id", "in", new_employee_fetch)]
|
|
employee_ids = odoo.env["hr.employee"].search(employee_domain)
|
|
|
|
# Map employee records to their user_ids for easier lookup
|
|
employee_by_user = {}
|
|
for emp_id in employee_ids:
|
|
emp = odoo.env["hr.employee"].browse(emp_id)
|
|
if emp.user_id:
|
|
employee_by_user[emp.user_id.id] = emp
|
|
|
|
# Process each salesperson that needs manager data
|
|
for salesperson_id in new_employee_fetch:
|
|
user_manager_partners_cache[salesperson_id] = []
|
|
|
|
# Skip if no employee record found
|
|
if salesperson_id not in employee_by_user:
|
|
continue
|
|
|
|
# Start with the employee record
|
|
current_employee = employee_by_user[salesperson_id]
|
|
|
|
# Walk up the management chain
|
|
while current_employee.parent_id:
|
|
manager = current_employee.parent_id
|
|
if manager.user_id:
|
|
# Cache the manager's partner ID if not already cached
|
|
if manager.user_id.id not in user_partner_cache:
|
|
manager_user = odoo.env["res.users"].browse(
|
|
manager.user_id.id
|
|
)
|
|
user_partner_cache[manager.user_id.id] = (
|
|
manager_user.partner_id.id
|
|
)
|
|
|
|
# Add this manager's partner ID to the salesperson's manager list
|
|
user_manager_partners_cache[salesperson_id].append(
|
|
user_partner_cache[manager.user_id.id]
|
|
)
|
|
|
|
# Move up the chain
|
|
current_employee = manager
|
|
|
|
# Process each contact in the batch
|
|
updates_by_partner = {}
|
|
|
|
for contact in batch_contacts:
|
|
salesperson_id = contact.user_id.id
|
|
|
|
if not salesperson_id:
|
|
continue
|
|
|
|
# Get the salesperson's partner ID
|
|
salesperson_partner_id = user_partner_cache.get(salesperson_id)
|
|
if not salesperson_partner_id:
|
|
continue
|
|
|
|
# Get the manager partner IDs for this salesperson
|
|
manager_partner_ids = user_manager_partners_cache.get(salesperson_id, [])
|
|
|
|
# Combine salesperson and manager partner IDs
|
|
partner_ids = [salesperson_partner_id] + manager_partner_ids
|
|
|
|
# Get current followers
|
|
current_followers = [f.partner_id.id for f in contact.message_follower_ids]
|
|
|
|
# Only add partners that are not already followers
|
|
partners_to_add = [p for p in partner_ids if p not in current_followers]
|
|
|
|
if partners_to_add:
|
|
updates_by_partner[contact.id] = partners_to_add
|
|
|
|
# Batch process the updates
|
|
for contact_id, partners in updates_by_partner.items():
|
|
try:
|
|
odoo.env["res.partner"].browse(contact_id).message_subscribe(
|
|
partner_ids=partners
|
|
)
|
|
print(f"Updated contact {contact.name} with partners {partners}")
|
|
batch_updated += 1
|
|
except Exception as e:
|
|
contact_name = odoo.env["res.partner"].browse(contact_id).name
|
|
print(f"Error updating contact {contact_name} (ID: {contact_id}): {e}")
|
|
|
|
total_updated += batch_updated
|
|
pbar.update(1)
|
|
pbar.set_postfix({"updated": batch_updated, "total_updated": total_updated})
|
|
|
|
pbar.close()
|
|
print(
|
|
f"Process completed. Updated {total_updated} out of {contact_count} contacts."
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|