Initial commit

This commit is contained in:
gsinghpal
2026-02-22 01:22:18 -05:00
commit 5200d5baf0
2394 changed files with 386834 additions and 0 deletions

View File

@@ -0,0 +1,191 @@
# -*- 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 base64
import csv
import json
import re
import io
from odoo import models, fields, api, _
from odoo.exceptions import UserError
import logging
_logger = logging.getLogger(__name__)
class DeviceCodeImportWizard(models.TransientModel):
_name = 'fusion_claims.device.import.wizard'
_description = 'Import ADP Device Codes from JSON/CSV'
file = fields.Binary(
string='File',
required=True,
help='Upload a JSON or CSV file containing device codes',
)
filename = fields.Char(string='Filename')
file_type = fields.Selection([
('json', 'JSON'),
('csv', 'CSV (ADP Mobility Manual)'),
], string='File Type', default='json', required=True)
# Results
state = fields.Selection([
('draft', 'Draft'),
('done', 'Done'),
], default='draft')
result_created = fields.Integer(string='Created', readonly=True)
result_updated = fields.Integer(string='Updated', readonly=True)
result_errors = fields.Text(string='Errors', readonly=True)
@api.onchange('filename')
def _onchange_filename(self):
"""Auto-detect file type from filename."""
if self.filename:
if self.filename.lower().endswith('.csv'):
self.file_type = 'csv'
elif self.filename.lower().endswith('.json'):
self.file_type = 'json'
def _parse_csv_content(self, content):
"""Parse CSV content to data list."""
data = []
# Try to decode as UTF-8 with BOM, then fallback
try:
text = content.decode('utf-8-sig')
except UnicodeDecodeError:
try:
text = content.decode('latin-1')
except Exception:
text = content.decode('utf-8', errors='ignore')
reader = csv.DictReader(io.StringIO(text))
# Log the column names for debugging
_logger.info("CSV columns detected: %s", reader.fieldnames)
for row in reader:
device_code = (row.get('Device Code', '') or '').strip()
if not device_code:
continue
# Find the price column - check multiple possible names
price = 0.0
price_column_names = [
'ADP Price', 'adp_price', 'Approved Price', ' Approved Price ',
'Price', 'price', 'ADP_Price', 'adp price'
]
# First try exact matches
for col_name in price_column_names:
if col_name in row:
price_str = row.get(col_name, '')
price_str = re.sub(r'[\$,"\'\s]', '', str(price_str))
try:
price = float(price_str)
if price > 0:
break
except ValueError:
pass
# If still 0, try partial match on column names
if price == 0:
for key in row.keys():
key_lower = key.lower().strip()
if 'price' in key_lower:
price_str = row.get(key, '')
price_str = re.sub(r'[\$,"\'\s]', '', str(price_str))
try:
price = float(price_str)
if price > 0:
_logger.info("Found price in column '%s': %s", key, price)
break
except ValueError:
pass
# Find the serial/SN required column - check multiple possible names
sn_required = 'No'
sn_column_names = [
'SN Required', 'sn_required', 'Serial', 'serial',
'SN', 'sn', 'Serial Number Required', 'Requires SN'
]
# First try exact matches
for col_name in sn_column_names:
if col_name in row:
sn_required = row.get(col_name, 'No')
break
# If not found, try partial match
if sn_required == 'No':
for key in row.keys():
key_lower = key.lower().strip()
if 'serial' in key_lower or 'sn' in key_lower:
sn_required = row.get(key, 'No')
_logger.info("Found SN in column '%s': %s", key, sn_required)
break
data.append({
'Device Type': row.get('Device Type', ''),
'Manufacturer': row.get('Manufacturer', ''),
'Device Description': row.get('Device Description', ''),
'Device Code': device_code,
'Quantity': row.get('Qty', 1) or row.get('Quantity', 1),
'ADP Price': price,
'SN Required': sn_required,
})
_logger.info("Parsed %d device codes from CSV", len(data))
return data
def action_import(self):
"""Import device codes from uploaded file."""
self.ensure_one()
if not self.file:
raise UserError(_("Please upload a file."))
try:
# Decode file
file_content = base64.b64decode(self.file)
if self.file_type == 'csv':
# Parse CSV
data = self._parse_csv_content(file_content)
else:
# Parse JSON
try:
text = file_content.decode('utf-8-sig')
except UnicodeDecodeError:
text = file_content.decode('utf-8')
data = json.loads(text)
except json.JSONDecodeError as e:
raise UserError(_("Invalid JSON file: %s") % str(e))
except Exception as e:
raise UserError(_("Error reading file: %s") % str(e))
if not data:
raise UserError(_("No valid data found in file."))
# Import using the model method
DeviceCode = self.env['fusion.adp.device.code']
result = DeviceCode.import_from_json(data)
# Update wizard with results
self.write({
'state': 'done',
'result_created': result['created'],
'result_updated': result['updated'],
'result_errors': '\n'.join(result['errors']) if result['errors'] else '',
})
return {
'type': 'ir.actions.act_window',
'res_model': self._name,
'res_id': self.id,
'view_mode': 'form',
'target': 'new',
}