# -*- 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. from odoo import models class ProductProduct(models.Model): _inherit = 'product.product' def get_adp_device_code(self): """ Get ADP device code from the field mapped in fusion settings. The field name is configured in Settings → Sales → Fusion Central → Field Mappings → Product ADP Code Field. Checks the mapped field on the product variant first, then on template. Returns the value from the mapped field, or empty string if not found. """ self.ensure_one() # Get the mapped field name from fusion settings ICP = self.env['ir.config_parameter'].sudo() field_name = ICP.get_param('fusion_claims.field_product_code', 'x_fc_adp_device_code') if not field_name: return '' # Check if the mapped field exists on the product variant (product.product) if field_name in self._fields: value = getattr(self, field_name, '') or '' if value: return value # Check if the mapped field exists on the product template if self.product_tmpl_id and field_name in self.product_tmpl_id._fields: value = getattr(self.product_tmpl_id, field_name, '') or '' if value: return value return '' def get_adp_price(self): """ Get ADP price from the field mapped in fusion settings. The field name is configured in Settings → Sales → Fusion Central → Field Mappings → Product ADP Price Field. Checks the mapped field on the product variant first, then on template. Returns the value from the mapped field, or 0.0 if not found. """ self.ensure_one() # Get the mapped field name from fusion settings ICP = self.env['ir.config_parameter'].sudo() field_name = ICP.get_param('fusion_claims.field_product_adp_price', 'x_fc_adp_price') if not field_name: return 0.0 # Check if the mapped field exists on the product variant (product.product) if field_name in self._fields: value = getattr(self, field_name, 0.0) or 0.0 if value: return value # Check if the mapped field exists on the product template if self.product_tmpl_id and field_name in self.product_tmpl_id._fields: value = getattr(self.product_tmpl_id, field_name, 0.0) or 0.0 if value: return value return 0.0 def is_non_adp_funded(self): """ Check if this product has a NON-ADP, NON-FUNDED, or UNFUNDED device code. Products with these device codes are not covered by ADP and should have: - ADP portion = 0 - Client portion = full amount - NOT included in ADP invoices (only in client invoices) Returns True if the product is NOT funded by ADP. """ self.ensure_one() # Get the ADP device code adp_code = self.get_adp_device_code() if not adp_code: return False # Check for non-funded codes (case-insensitive) # These product codes indicate items NOT covered by ADP funding: # - NON-ADP, NON-FUNDED, UNFUNDED: Explicitly not ADP funded # - ACS: Accessibility items (client pays 100%) # - ODS: ODSP items (client pays 100%) # - OWP: Ontario Works items (client pays 100%) non_funded_codes = [ 'NON-ADP', 'NON ADP', 'NONADP', 'NON-FUNDED', 'NON FUNDED', 'NONFUNDED', 'UNFUNDED', 'NOT-FUNDED', 'NOT FUNDED', 'NOTFUNDED', 'ACS', 'ODS', 'OWP' ] adp_code_upper = adp_code.upper().strip() for non_funded in non_funded_codes: if adp_code_upper == non_funded or adp_code_upper.startswith(non_funded): return True return False def action_sync_adp_price_from_database(self): """ Update product's ADP price from the device codes database. Looks up the product's ADP device code in the fusion.adp.device.code table and updates the product's x_fc_adp_price field with the database value. Returns a notification with the result. """ ADPDevice = self.env['fusion.adp.device.code'].sudo() updated = [] not_found = [] no_code = [] for product in self: device_code = product.get_adp_device_code() if not device_code: no_code.append(product.name) continue adp_device = ADPDevice.search([ ('device_code', '=', device_code), ('active', '=', True) ], limit=1) if adp_device and adp_device.adp_price: # Update product template product_tmpl = product.product_tmpl_id old_price = 0 if hasattr(product_tmpl, 'x_fc_adp_price'): old_price = getattr(product_tmpl, 'x_fc_adp_price', 0) or 0 product_tmpl.sudo().write({'x_fc_adp_price': adp_device.adp_price}) updated.append({ 'name': product.name, 'code': device_code, 'old_price': old_price, 'new_price': adp_device.adp_price, }) else: not_found.append(f"{product.name} ({device_code})") # Build result message message_parts = [] if updated: msg = f"Updated {len(updated)} product(s):" message_parts.append(msg) if not_found: message_parts.append(f"Not found in database: {', '.join(not_found)}") if no_code: message_parts.append(f"No ADP code: {', '.join(no_code)}") if not message_parts: message_parts.append("No products to process.") return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': 'ADP Price Sync', 'message': '
'.join(message_parts), 'type': 'success' if updated else 'warning', 'sticky': True, } }