update delete records
This commit is contained in:
parent
59083f02f7
commit
9086b4d26d
@ -34,6 +34,7 @@ import argparse
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import color_log
|
import color_log
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
# Load environment variables
|
# Load environment variables
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
HOST = os.getenv("HOST", "localhost")
|
HOST = os.getenv("HOST", "localhost")
|
||||||
@ -96,10 +97,26 @@ except Exception as e:
|
|||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_related_fields_for_model(model, base_model):
|
||||||
|
"""Fetch related fields for a single model."""
|
||||||
|
related_fields = {}
|
||||||
|
try:
|
||||||
|
fields = odoo.env[model].fields_get()
|
||||||
|
for field_name, field_info in fields.items():
|
||||||
|
if (
|
||||||
|
field_info.get("type") in ["many2one", "many2many", "one2many"]
|
||||||
|
and field_info.get("relation") == base_model
|
||||||
|
):
|
||||||
|
related_fields.setdefault(model, []).append(field_name)
|
||||||
|
except Exception as e:
|
||||||
|
color_log.Show(3, f"Skipping model {model}: {e}")
|
||||||
|
return related_fields
|
||||||
|
|
||||||
|
|
||||||
# Function to fetch related models
|
# Function to fetch related models
|
||||||
def get_related_fields(db_name, base_model):
|
def get_related_fields(db_name, base_model):
|
||||||
"""Fetch related fields for a given model, using a cached file to reduce API calls."""
|
"""Fetch related fields for a given model using multiprocessing."""
|
||||||
cache_file = f"cache/{db_name}-{base_model}.cache.json"
|
cache_file = f"cache/{db_name}/{base_model}.cache.json"
|
||||||
|
|
||||||
if os.path.exists(cache_file):
|
if os.path.exists(cache_file):
|
||||||
with open(cache_file, "r") as f:
|
with open(cache_file, "r") as f:
|
||||||
@ -112,29 +129,34 @@ def get_related_fields(db_name, base_model):
|
|||||||
try:
|
try:
|
||||||
all_model_ids = odoo.env["ir.model"].search([])
|
all_model_ids = odoo.env["ir.model"].search([])
|
||||||
all_models = odoo.env["ir.model"].read(all_model_ids, ["model"])
|
all_models = odoo.env["ir.model"].read(all_model_ids, ["model"])
|
||||||
|
model_names = [model["model"] for model in all_models]
|
||||||
|
|
||||||
for model in all_models:
|
# Use multiprocessing to fetch related fields
|
||||||
model_name = model["model"]
|
with mp.Pool(processes=process_size) as pool:
|
||||||
try:
|
results = pool.starmap(
|
||||||
fields = odoo.env[model_name].fields_get()
|
fetch_related_fields_for_model,
|
||||||
for field_name, field_info in fields.items():
|
[(model_name, base_model) for model_name in model_names],
|
||||||
if (
|
)
|
||||||
field_info.get("type") in ["many2one", "many2many", "one2many"]
|
|
||||||
and field_info.get("relation") == base_model
|
|
||||||
):
|
|
||||||
related_models.setdefault(model_name, []).append(field_name)
|
|
||||||
except Exception as e:
|
|
||||||
color_log.Show(3, f"Skipping model {model_name}: {e}")
|
|
||||||
|
|
||||||
|
# Combine results from all processes
|
||||||
|
for result in results:
|
||||||
|
for model, fields in result.items():
|
||||||
|
related_models.setdefault(model, []).extend(fields)
|
||||||
|
|
||||||
|
# Save to cache
|
||||||
|
os.makedirs(os.path.dirname(cache_file), exist_ok=True)
|
||||||
with open(cache_file, "w") as f:
|
with open(cache_file, "w") as f:
|
||||||
json.dump(related_models, f, indent=4)
|
json.dump(related_models, f, indent=4)
|
||||||
|
|
||||||
return related_models
|
return related_models
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
color_log.Show(3, f"Error fetching related models: {e}")
|
color_log.Show(3, f"Error fetching related models: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def delete_records_cascade(record_ids, model_name, process_count, related_models, db_name):
|
def delete_records_cascade(
|
||||||
|
record_ids, model_name, process_count, related_models, db_name
|
||||||
|
):
|
||||||
"""Iteratively delete related records before deleting the base records"""
|
"""Iteratively delete related records before deleting the base records"""
|
||||||
# Stack for traversal: list of (model_name, record_ids) tuples
|
# Stack for traversal: list of (model_name, record_ids) tuples
|
||||||
stack = [(model_name, record_ids)]
|
stack = [(model_name, record_ids)]
|
||||||
@ -152,15 +174,21 @@ def delete_records_cascade(record_ids, model_name, process_count, related_models
|
|||||||
visited.update(current_pairs)
|
visited.update(current_pairs)
|
||||||
has_dependents = False
|
has_dependents = False
|
||||||
|
|
||||||
for related_model, fields in get_related_fields(db_name, current_model).items():
|
for related_model, fields in get_related_fields(
|
||||||
|
db_name, current_model
|
||||||
|
).items():
|
||||||
related_model_obj = odoo.env[related_model]
|
related_model_obj = odoo.env[related_model]
|
||||||
for field in fields:
|
for field in fields:
|
||||||
try:
|
try:
|
||||||
related_ids = related_model_obj.search([(field, "in", current_ids)])
|
related_ids = related_model_obj.search(
|
||||||
|
[(field, "in", current_ids)]
|
||||||
|
)
|
||||||
if related_ids:
|
if related_ids:
|
||||||
stack.append((related_model, related_ids))
|
stack.append((related_model, related_ids))
|
||||||
has_dependents = True
|
has_dependents = True
|
||||||
print(f"{process_count}: Found {len(related_ids)} related records in {related_model} ({field})")
|
print(
|
||||||
|
f"{process_count}: Found {len(related_ids)} related records in {related_model} ({field})"
|
||||||
|
)
|
||||||
process_count += 1
|
process_count += 1
|
||||||
except odoorpc.error.RPCError as e:
|
except odoorpc.error.RPCError as e:
|
||||||
print(f"Access denied for model {related_model}: {e}")
|
print(f"Access denied for model {related_model}: {e}")
|
||||||
@ -250,7 +278,7 @@ def main():
|
|||||||
]
|
]
|
||||||
processes = []
|
processes = []
|
||||||
if args.force:
|
if args.force:
|
||||||
delete_records_cascade(record_ids, base_model, 0, related_models,db_name)
|
delete_records_cascade(record_ids, base_model, 0, related_models, db_name)
|
||||||
# for i, batch in enumerate(batch_list, start=1):
|
# for i, batch in enumerate(batch_list, start=1):
|
||||||
# process = mp.Process(
|
# process = mp.Process(
|
||||||
# target=delete_records_cascade,
|
# target=delete_records_cascade,
|
||||||
|
Loading…
Reference in New Issue
Block a user