Files
Implementation_ITSA/Reference Data/python_project/scripts/import_price_index.py
AzureAD\SylvainDUVERNAY 3a3e715336 Commit all views
2026-05-11 14:01:13 +02:00

224 lines
8.2 KiB
Python

# Add parent directory to Python path so we can import helpers
import sys
from pathlib import Path
parent_dir = Path(__file__).parent.parent
sys.path.insert(0, str(parent_dir))
import csv
from proteus import Model
from helpers.config import (
PRICE_INDEXES_CSV,
connect_to_tryton,
)
CSV_FILE_PATH = PRICE_INDEXES_CSV
# ---------------------------------------------------------------------------
# Main import function
# ---------------------------------------------------------------------------
def import_price_indexes(csv_file):
PriceIndex = Model.get('price.price')
ProductMonth = Model.get('product.month')
Currency = Model.get('currency.currency')
PriceFixType = Model.get('price.fixtype')
ProductUom = Model.get('product.uom')
print(f"{'='*70}")
print(f"IMPORTING PRICE INDEXES FROM CSV")
print(f"{'='*70}\n")
print(f"Reading from: {csv_file}\n")
imported_count = 0
skipped_count = 0
error_count = 0
ignored = [] # list of (row_num, price_index, reason)
errors = [] # list of error strings
# Build lookup maps upfront to avoid repeated DB calls
print("Loading existing price indexes...")
all_indexes = PriceIndex.find([])
index_map = {pi.price_index: pi for pi in all_indexes}
print(f" Found {len(index_map)} price indexes in database\n")
print("Loading product months...")
all_months = ProductMonth.find([])
month_map = {pm.month_name: pm for pm in all_months}
print(f" Found {len(month_map)} product months in database\n")
print("Loading reference data (currencies, price types, units)...")
currency_map = {c.id: c for c in Currency.find([])}
fixtype_map = {pft.id: pft for pft in PriceFixType.find([])}
uom_map = {u.id: u for u in ProductUom.find([])}
print()
row_num = 0
try:
with open(csv_file, 'r', encoding='utf-8-sig') as file:
reader = csv.DictReader(file)
for row in reader:
row_num += 1
index_name = row.get('price_index', '').strip()
try:
print(f"{'='*70}")
print(f"Row {row_num}: {index_name}")
print(f"{'='*70}")
if not index_name:
raise ValueError("price_index is empty")
# Already exists → skip silently
if index_name in index_map:
print(f" ⏭ Already exists in database — skipping\n")
ignored.append((row_num, index_name, "Already exists in price_price"))
skipped_count += 1
continue
# Lookup pricing period in product_month
period_label = row.get('pricing_period_label', '').strip()
if not period_label:
msg = "pricing_period_label is empty"
print(f"{msg} — not imported\n")
ignored.append((row_num, index_name, msg))
skipped_count += 1
continue
product_month = month_map.get(period_label)
if not product_month:
# Case-insensitive fallback
for k, v in month_map.items():
if k and k.upper() == period_label.upper():
product_month = v
break
if not product_month:
msg = f"pricing_period_label '{period_label}' not found in product_month"
print(f"{msg} — not imported\n")
ignored.append((row_num, index_name, msg))
skipped_count += 1
continue
# Resolve FK: currency
raw_currency = row.get('price_currency', '').strip()
currency = None
if raw_currency:
try:
currency = currency_map.get(int(raw_currency))
except (ValueError, TypeError):
pass
if not currency:
raise ValueError(f"price_currency id '{raw_currency}' not found in currency_currency")
# Resolve FK: price type (optional)
raw_type = row.get('price_type', '').strip()
price_type = None
if raw_type:
try:
price_type = fixtype_map.get(int(raw_type))
except (ValueError, TypeError):
pass
# Resolve FK: unit of measure (optional)
raw_unit = row.get('price_unit', '').strip()
price_unit = None
if raw_unit:
try:
price_unit = uom_map.get(int(raw_unit))
except (ValueError, TypeError):
pass
# Scalar fields
price_desc = row.get('price_desc', '').strip()
price_curve_type = row.get('price_curve_type', '').strip()
active_raw = row.get('active', 'TRUE').strip().upper()
active = active_raw in ('TRUE', '1', 'YES')
# Create the record
print(f" Creating price index...")
record = PriceIndex()
record.price_index = index_name
record.price_desc = price_desc
record.price_currency = currency
record.price_curve_type = price_curve_type
record.price_period = product_month
record.active = active
if price_type:
record.price_type = price_type
if price_unit:
record.price_unit = price_unit
record.save()
print(f" ✓ Created (ID: {record.id})")
print(f" Index : {index_name}")
print(f" Period : {period_label} (ID: {product_month.id})")
print(f" Desc : {price_desc}")
print()
imported_count += 1
except Exception as e:
error_msg = f"Row {row_num} - {index_name or 'Unknown'}: {str(e)}"
errors.append(error_msg)
error_count += 1
print(f" ✗ Error on row {row_num}: {e}\n")
import traceback
traceback.print_exc()
except FileNotFoundError:
print(f"✗ Error: CSV file not found at {csv_file}")
print(f"Please update PRICE_INDEXES_CSV in helpers/config.py with the correct path.")
return
except Exception as e:
print(f"✗ Fatal error: {e}")
import traceback
traceback.print_exc()
return
# Summary
print(f"\n{'='*70}")
print("IMPORT SUMMARY")
print(f"{'='*70}")
print(f"Total rows processed : {row_num}")
print(f"Successfully imported : {imported_count}")
print(f"Skipped / Not imported : {skipped_count}")
print(f"Errors : {error_count}")
if ignored:
print(f"\nIgnored / Not imported ({len(ignored)}):")
for r, name, reason in ignored:
print(f" - Row {r:>4} [{name}]: {reason}")
if errors:
print(f"\nErrors ({len(errors)}):")
for err in errors:
print(f" - {err}")
print(f"\n{'='*70}")
# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------
def main():
print("=" * 70)
print("TRYTON PRICE INDEX IMPORT SCRIPT")
print("Using Proteus with XML-RPC Connection")
print("=" * 70)
print()
if not connect_to_tryton():
return 1
import_price_indexes(CSV_FILE_PATH)
return 0
if __name__ == '__main__':
exit(main())