# Generated by Django on 2026-06-10 from django.db import migrations from django.contrib.auth.hashers import make_password from django.conf import settings import zipfile import xml.etree.ElementTree as ET import unicodedata import random import string import os def normalize_text(text): nfkd_form = unicodedata.normalize('NFKD', text) only_ascii = "".join([c for c in nfkd_form if not unicodedata.combining(c)]) cleaned = "".join([c.lower() for c in only_ascii if c.isalnum()]) return cleaned def generate_password(): first_char = random.choice(string.ascii_uppercase) rest_chars = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(11)) return first_char + rest_chars def create_agents_regie(apps, schema_editor): User = apps.get_model('auth', 'User') Role = apps.get_model('common', 'Role') UserConfig = apps.get_model('common', 'UserConfig') Company = apps.get_model('contracts', 'Company') CompanyMember = apps.get_model('contracts', 'CompanyMember') # Find the ODS file path ods_path = os.path.join(settings.BASE_DIR, '..', 'external_files', 'agents_regie.ods') if not os.path.exists(ods_path): ods_path = os.path.join(settings.BASE_DIR, 'external_files', 'agents_regie.ods') if not os.path.exists(ods_path): print(f"\n[WARNING] agents_regie.ods not found at {ods_path}. Skipping user creation.") return # Parse ODS file namespaces = { 'table': 'urn:oasis:names:tc:opendocument:xmlns:table:1.0', 'text': 'urn:oasis:names:tc:opendocument:xmlns:text:1.0', 'office': 'urn:oasis:names:tc:opendocument:xmlns:office:1.0' } agents = [] with zipfile.ZipFile(ods_path, 'r') as z: content_xml = z.read('content.xml') root = ET.fromstring(content_xml) tables = root.findall('.//table:table', namespaces) for table in tables: rows = table.findall('.//table:table-row', namespaces) for idx, row in enumerate(rows): cells = [] for cell in row.findall('.//table:table-cell', namespaces): repeated = cell.get('{' + namespaces['table'] + '}number-columns-repeated') rep_count = int(repeated) if repeated else 1 text_elems = cell.findall('.//text:p', namespaces) cell_text = "".join([t.text if t.text else "" for t in text_elems]) for _ in range(rep_count): cells.append(cell_text) if any(cells): while cells and cells[-1] == "": cells.pop() if idx == 0: continue if len(cells) >= 2: name = cells[0].strip() firstname = cells[1].strip() if name and firstname: agents.append((name, firstname)) if not agents: print("\n[WARNING] No agents found in agents_regie.ods. Skipping.") return role_tech, _ = Role.objects.get_or_create(name='technician') company_regie, _ = Company.objects.get_or_create(name='BM - Régie') created_users = [] passwords_file_lines = [ "=== BM - Régie : Nouveaux Techniciens ===", f"Généré le : {os.getenv('CURRENT_TIME', '2026-06-10')}", "-" * 50 ] for name, firstname in agents: last_name_formatted = name.capitalize() first_name_formatted = firstname first_letter = normalize_text(first_name_formatted)[:1] last_name_normalized = normalize_text(last_name_formatted) username = f"{first_letter}{last_name_normalized}" if User.objects.filter(username=username).exists(): continue password = generate_password() # Create user user = User.objects.create( username=username, first_name=first_name_formatted, last_name=last_name_formatted, password=make_password(password) ) # Create UserConfig config = UserConfig.objects.create( user=user, company=company_regie ) config.roles.add(role_tech) # Create CompanyMember CompanyMember.objects.create( user=user, name=first_name_formatted ) created_users.append((username, password)) passwords_file_lines.append(f"Login: {username:<15} | Password: {password}") if created_users: print("\n" + "="*80) print("BM - RÉGIE : UTILISATEURS CRÉÉS") print("="*80) for username, password in created_users: print(f" Login: {username:<15} | Mot de passe: {password}") print("="*80) # Write to generated_passwords.txt on production server passwords_file_path = os.path.join(settings.BASE_DIR, 'generated_passwords.txt') try: with open(passwords_file_path, 'w', encoding='utf-8') as f: f.write("\n".join(passwords_file_lines) + "\n") print(f"Mots de passe sauvegardés dans : {passwords_file_path}") except Exception as e: print(f"[ERROR] Impossible d'écrire les mots de passe dans un fichier: {e}") print("="*80 + "\n") def delete_agents_regie(apps, schema_editor): pass class Migration(migrations.Migration): dependencies = [ ('common', '0007_userconfig_esign_organizations'), ('contracts', '0006_companymember_teams_m2m'), ] operations = [ migrations.RunPython(create_agents_regie, reverse_code=delete_agents_regie), ]