Files
Odoo-Modules/fusion_claims/scripts/import_adp_mobility_manual.py
2026-02-22 01:22:18 -05:00

197 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ADP Mobility Manual CSV to JSON Converter
This script reads the ADP Mobility Manual CSV file, cleans the data,
and outputs a JSON file that can be imported into Odoo's fusion.adp.device.code model.
Usage:
python import_adp_mobility_manual.py input.csv output.json
Or run without arguments to use default paths.
Copyright 2024-2025 Nexa Systems Inc.
License OPL-1 (Odoo Proprietary License v1.0)
"""
import csv
import json
import re
import sys
import os
def clean_text(text):
"""Clean text from weird characters, normalize encoding."""
if not text:
return ''
# Convert to string if not already
text = str(text)
# Replace curly quotes with straight quotes
text = text.replace('"', '"').replace('"', '"')
text = text.replace(''', "'").replace(''', "'")
# Replace various dashes with standard hyphen
text = text.replace('', '-').replace('', '-')
# Remove non-printable characters except newlines
text = ''.join(char if char.isprintable() or char in '\n\r\t' else ' ' for char in text)
# Normalize multiple spaces
text = re.sub(r'\s+', ' ', text)
# Strip leading/trailing whitespace
return text.strip()
def parse_price(price_str):
"""Parse price string like '$64.00' or '$2,578.00' to float."""
if not price_str:
return 0.0
# Remove currency symbols, commas, spaces, quotes
price_str = str(price_str).strip()
price_str = re.sub(r'[\$,"\'\s]', '', price_str)
try:
return float(price_str)
except ValueError:
return 0.0
def convert_csv_to_json(input_path, output_path):
"""Convert ADP Mobility Manual CSV to JSON format."""
data = []
errors = []
skipped = 0
# Try different encodings
encodings = ['utf-8-sig', 'utf-8', 'latin-1', 'cp1252']
content = None
for encoding in encodings:
try:
with open(input_path, 'r', encoding=encoding) as f:
content = f.read()
break
except UnicodeDecodeError:
continue
if content is None:
print(f"Error: Could not read file with any known encoding")
return None
# Parse CSV
reader = csv.DictReader(content.splitlines())
for idx, row in enumerate(reader, start=2): # Start at 2 (header is line 1)
try:
# Get device code - skip if empty
device_code = clean_text(row.get('Device Code', ''))
if not device_code:
skipped += 1
continue
# Get device type
device_type = clean_text(row.get('Device Type', ''))
if not device_type:
skipped += 1
continue
# Get manufacturer
manufacturer = clean_text(row.get('Manufacturer', ''))
# Get device description - clean it
device_description = clean_text(row.get('Device Description', ''))
# Parse quantity
qty_str = row.get('Qty', '1') or '1'
try:
quantity = int(qty_str)
except ValueError:
quantity = 1
# Parse price (handle both ' Approved Price ' with spaces and 'Approved Price')
price = 0.0
for key in row.keys():
if 'price' in key.lower() and 'approved' in key.lower():
price = parse_price(row.get(key, ''))
break
# Parse serial requirement
serial_str = clean_text(row.get('Serial', 'No')).upper()
sn_required = serial_str in ('YES', 'Y', 'TRUE', '1')
data.append({
'Device Type': device_type,
'Manufacturer': manufacturer,
'Device Description': device_description,
'Device Code': device_code,
'Quantity': quantity,
'ADP Price': price,
'SN Required': 'Yes' if sn_required else 'No',
})
except Exception as e:
errors.append(f"Row {idx}: {str(e)}")
# Write JSON output
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# Print summary
print(f"\n{'='*60}")
print(f"ADP Mobility Manual Import Summary")
print(f"{'='*60}")
print(f"Input file: {input_path}")
print(f"Output file: {output_path}")
print(f"Records processed: {len(data)}")
print(f"Records skipped: {skipped}")
print(f"Errors: {len(errors)}")
if errors:
print(f"\nFirst 10 errors:")
for err in errors[:10]:
print(f" - {err}")
# Print device type summary
device_types = {}
for item in data:
dt = item['Device Type']
device_types[dt] = device_types.get(dt, 0) + 1
print(f"\nDevice Types ({len(device_types)} unique):")
for dt in sorted(device_types.keys())[:20]:
print(f" - {dt}: {device_types[dt]} devices")
if len(device_types) > 20:
print(f" ... and {len(device_types) - 20} more")
print(f"\n{'='*60}")
print(f"JSON file ready for import into Odoo!")
print(f"Use: Sales > Configuration > ADP Device Codes > Import")
print(f"{'='*60}\n")
return data
def main():
# Default paths
default_input = r"C:\Users\gur_p\Downloads\ADP-Mobility-Manual.csv"
default_output = r"C:\Users\gur_p\Downloads\ADP-Mobility-Manual-cleaned.json"
if len(sys.argv) >= 3:
input_path = sys.argv[1]
output_path = sys.argv[2]
elif len(sys.argv) == 2:
input_path = sys.argv[1]
output_path = os.path.splitext(input_path)[0] + '-cleaned.json'
else:
input_path = default_input
output_path = default_output
if not os.path.exists(input_path):
print(f"Error: Input file not found: {input_path}")
print(f"\nUsage: python {sys.argv[0]} input.csv [output.json]")
sys.exit(1)
convert_csv_to_json(input_path, output_path)
if __name__ == '__main__':
main()