from datetime import datetime from xml.dom import minidom from dataclasses import dataclass import os import csv import logging from typing import List logger = logging.getLogger('application') logger.setLevel(logging.INFO) fh = logging.FileHandler('app.log', encoding='utf-8') logger.addHandler(fh) class DNaPlanGenerator: @dataclass class DataNode: fam: str = '' im: str = '' ot: str = '' dr: str = '' w: str = '' npolis: str = '' mes: str = '' nzap: str = '' mcode: str = '' def to_dict(self) -> dict: return { 'N_ZAP': self.nzap, 'FAM': self.fam, 'IM': self.im, 'OT': self.ot, 'W': self.w, 'DR': self.dr, 'NPOLIS': self.npolis, 'MDP': '0', 'SMOCOD': '35003', 'DISP_TYP': '6', 'MES': self.mes, } def __init__(self, mo_code: str, year: int, month: int): self.mo_code = mo_code self.year = 2026 self.month = month self.doc = minidom.Document() self.root = self.doc.createElement('ZL_LIST') self.xml_name = f'D-M{self.mo_code}-F35-2026-{month}' self.root.appendChild(self.header()) self.doc.appendChild(self.root) def header(self): zglv_tag = self.doc.createElement('ZGLV') fname_tag = self.doc.createElement('FILENAME') fname_tag.appendChild(self.doc.createTextNode(self.xml_name)) data_tag = self.doc.createElement('DATA') data_tag.appendChild(self.doc.createTextNode( datetime.now().strftime('%Y-%m-%d'))) mo_tag = self.doc.createElement('CODE_MO') mo_tag.appendChild(self.doc.createTextNode(self.mo_code)) year_tag = self.doc.createElement('YEAR') year_tag.appendChild(self.doc.createTextNode(str(self.year))) r_tag = self.doc.createElement('R') r_tag.appendChild(self.doc.createTextNode(str(self.month))) for item in (fname_tag, data_tag, mo_tag, year_tag, r_tag): zglv_tag.appendChild(item) return zglv_tag def fill(self, data: List[dict]): for node_data in data: node = self.DataNode(**node_data) zap_tag = self.doc.createElement('ZAP') for tag_name, tag_value in node.to_dict().items(): t = self.doc.createElement(tag_name) t.appendChild(self.doc.createTextNode(str(tag_value))) zap_tag.appendChild(t) self.root.appendChild(zap_tag) def save(self): xml_path = os.path.join(os.getcwd(), f'{self.xml_name}.xml') with open(xml_path, 'w', encoding='cp1251') as f: f.write(self.doc.toprettyxml(indent='\t', encoding='windows-1251').decode('cp1251')) logger.info(f'Файл успешно создан: {xml_path}') if __name__ == '__main__': mo_code = input('Введите код МО (6 цифр, например, 352530): ').strip() if not (mo_code.isdigit() and len(mo_code) == 6): print('Некорректный код МО. Нужно ввести ровно 6 цифр, например 352530.') exit(1) number_package = input('Введите порядковый номер пакета: ') year_now = datetime.now().year csv_filename = f"{mo_code}.csv" csv_path = os.path.join(os.getcwd(), csv_filename) if not os.path.exists(csv_path): print('Файл не найден!') exit(1) data_list = [] seen_policies = set() mes_counter = 1 with open(csv_path, encoding='utf-8') as f: reader = csv.reader(f, delimiter=';') for i, row in enumerate(reader, start=1): try: fam, im, ot, dr, npolis, w = row[:6] if npolis in seen_policies: continue seen_policies.add(npolis) try: dr_obj = datetime.strptime(dr, '%d.%m.%Y') dr_iso = dr_obj.strftime('%Y-%m-%d') except ValueError: logger.warning(f'Ошибка формата даты в строке {i}: {dr}') dr_iso = dr data_list.append({ 'fam': fam, 'im': im, 'ot': ot, 'dr': dr_iso, 'w': w, 'npolis': npolis, 'mes': mes_counter, 'nzap': str(i), 'mcode': mo_code }) mes_counter += 1 if mes_counter > 12: mes_counter = 1 except Exception as e: logger.warning(f'Ошибка в строке {i}: {e}') generator = DNaPlanGenerator(mo_code, year_now, int(number_package)) generator.fill(data_list) generator.save() print('✅ XML-файл успешно создан!')