127 lines
7.3 KiB
Python
127 lines
7.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2024-2025 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
# Part of the Fusion Claim Assistant product family.
|
|
|
|
import logging
|
|
from odoo import models, api, _
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class FusionCentralConfig(models.TransientModel):
|
|
_name = 'fusion_claims.config'
|
|
_description = 'Fusion Central Configuration Manager'
|
|
|
|
# =========================================================================
|
|
# ACTION METHODS
|
|
# =========================================================================
|
|
|
|
def action_detect_existing_fields(self):
|
|
"""Detect existing custom x_* fields and map them."""
|
|
ICP = self.env['ir.config_parameter'].sudo()
|
|
IrModelFields = self.env['ir.model.fields'].sudo()
|
|
detected = []
|
|
detected_details = []
|
|
|
|
# Search for all custom fields on relevant models
|
|
models_to_search = ['sale.order', 'sale.order.line', 'account.move', 'account.move.line', 'product.template']
|
|
|
|
# Find all custom x_* fields
|
|
all_custom_fields = IrModelFields.search([
|
|
('model', 'in', models_to_search),
|
|
('name', '=like', 'x_%'),
|
|
('state', '=', 'manual'),
|
|
])
|
|
|
|
_logger.debug("Found %d custom fields across models", len(all_custom_fields))
|
|
|
|
# Field patterns to detect (model, keywords, param_key, display_name)
|
|
# Keywords are checked if they appear anywhere in the field name
|
|
# NOTE: param_key must match the config_parameter in res_config_settings.py
|
|
field_mappings = [
|
|
# Sale Order header fields
|
|
('sale.order', ['sale_type', 'saletype', 'type_of_sale'], 'fusion_claims.field_sale_type', 'Sale Type'),
|
|
('sale.order', ['client_type', 'clienttype', 'customer_type'], 'fusion_claims.field_so_client_type', 'SO Client Type'),
|
|
('sale.order', ['authorizer', 'authorized', 'approver'], 'fusion_claims.field_so_authorizer', 'SO Authorizer'),
|
|
('sale.order', ['claim_number', 'claimnumber', 'claim_no', 'claim_num'], 'fusion_claims.field_so_claim_number', 'SO Claim Number'),
|
|
('sale.order', ['client_ref_1', 'clientref1', 'reference_1'], 'fusion_claims.field_so_client_ref_1', 'SO Client Ref 1'),
|
|
('sale.order', ['client_ref_2', 'clientref2', 'reference_2'], 'fusion_claims.field_so_client_ref_2', 'SO Client Ref 2'),
|
|
('sale.order', ['delivery_date', 'deliverydate', 'adp_delivery'], 'fusion_claims.field_so_delivery_date', 'SO Delivery Date'),
|
|
('sale.order', ['service_start', 'servicestart'], 'fusion_claims.field_so_service_start', 'SO Service Start'),
|
|
('sale.order', ['service_end', 'serviceend'], 'fusion_claims.field_so_service_end', 'SO Service End'),
|
|
('sale.order', ['adp_status', 'adpstatus'], 'fusion_claims.field_so_adp_status', 'SO ADP Status'),
|
|
# Sale Order line fields
|
|
('sale.order.line', ['serial', 'sn', 's_n'], 'fusion_claims.field_sol_serial', 'SO Line Serial'),
|
|
('sale.order.line', ['placement', 'device_placement'], 'fusion_claims.field_sol_placement', 'SO Line Placement'),
|
|
# Invoice header fields
|
|
('account.move', ['invoice_type', 'invoicetype', 'inv_type', 'type_of_invoice'], 'fusion_claims.field_invoice_type', 'Invoice Type'),
|
|
('account.move', ['client_type', 'clienttype', 'customer_type'], 'fusion_claims.field_inv_client_type', 'Invoice Client Type'),
|
|
('account.move', ['authorizer', 'authorized', 'approver'], 'fusion_claims.field_inv_authorizer', 'Invoice Authorizer'),
|
|
('account.move', ['claim_number', 'claimnumber', 'claim_no'], 'fusion_claims.field_inv_claim_number', 'Invoice Claim Number'),
|
|
('account.move', ['client_ref_1', 'clientref1', 'reference_1'], 'fusion_claims.field_inv_client_ref_1', 'Invoice Client Ref 1'),
|
|
('account.move', ['client_ref_2', 'clientref2', 'reference_2'], 'fusion_claims.field_inv_client_ref_2', 'Invoice Client Ref 2'),
|
|
('account.move', ['delivery_date', 'deliverydate', 'adp_delivery'], 'fusion_claims.field_inv_delivery_date', 'Invoice Delivery Date'),
|
|
('account.move', ['service_start', 'servicestart'], 'fusion_claims.field_inv_service_start', 'Invoice Service Start'),
|
|
('account.move', ['service_end', 'serviceend'], 'fusion_claims.field_inv_service_end', 'Invoice Service End'),
|
|
# Invoice line fields
|
|
('account.move.line', ['serial', 'sn', 's_n'], 'fusion_claims.field_aml_serial', 'Invoice Line Serial'),
|
|
('account.move.line', ['placement', 'device_placement'], 'fusion_claims.field_aml_placement', 'Invoice Line Placement'),
|
|
# Product fields
|
|
('product.template', ['adp_device', 'adp_code', 'adp_sku', 'device_code', 'sku'], 'fusion_claims.field_product_code', 'Product ADP Code'),
|
|
]
|
|
|
|
for model, keywords, param_key, display_name in field_mappings:
|
|
# Find fields on this model that contain any of the keywords
|
|
model_fields = all_custom_fields.filtered(lambda f: f.model == model)
|
|
|
|
model_fields_sorted = sorted(model_fields, key=lambda f: f.name)
|
|
|
|
matched_field = None
|
|
for field in model_fields_sorted:
|
|
field_name_lower = field.name.lower()
|
|
for keyword in keywords:
|
|
if keyword in field_name_lower:
|
|
# Skip our own x_fc_* fields - we want to find other custom fields
|
|
if field.name.startswith('x_fc_'):
|
|
continue
|
|
matched_field = field
|
|
break
|
|
if matched_field:
|
|
break
|
|
|
|
if matched_field:
|
|
ICP.set_param(param_key, matched_field.name)
|
|
detected.append(matched_field.name)
|
|
detected_details.append(f"• {display_name}: {matched_field.name} ({model})")
|
|
_logger.debug("Mapped %s -> %s on %s", param_key, matched_field.name, model)
|
|
|
|
# Also list any unmapped custom fields for reference
|
|
unmapped = []
|
|
for field in all_custom_fields:
|
|
if field.name not in detected:
|
|
unmapped.append(f"{field.model}.{field.name}")
|
|
|
|
if detected_details:
|
|
message = _("Detected and mapped %d fields:\n%s") % (len(detected), "\n".join(detected_details))
|
|
if unmapped:
|
|
message += _("\n\nOther custom fields found (not mapped):\n• ") + "\n• ".join(unmapped[:10])
|
|
if len(unmapped) > 10:
|
|
message += f"\n... and {len(unmapped) - 10} more"
|
|
message += _("\n\n⚠️ IMPORTANT: Save settings and reload page to see changes.")
|
|
else:
|
|
message = _("No matching fields found.\n\nCustom fields found:\n• ") + "\n• ".join(unmapped[:15]) if unmapped else _("No custom fields found on relevant models.")
|
|
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'title': _("Field Detection Complete"),
|
|
'message': message,
|
|
'type': 'success' if detected else 'warning',
|
|
'sticky': True,
|
|
}
|
|
}
|
|
|
|
# (Migration and field protection methods removed)
|