#!/usr/bin/env python3 """ ACT Maker - Gradio Web Interface for Hugging Face Spaces Web interface for generating ACT documents from ESFS XML receipts. """ import os import shutil import tempfile import zipfile import gradio as gr from utils import NumberToWords, DocumentProcessor, ReceiptParser, DocumentMerger # Global variable to store template path TEMPLATE_PATH = None def extract_template(): """Extract draft.docx from encrypted zip file""" global TEMPLATE_PATH if TEMPLATE_PATH and os.path.exists(TEMPLATE_PATH): return TEMPLATE_PATH # Get password from environment variable zip_password = os.getenv('ZIP_KEY') if not zip_password: raise ValueError("ZIP_KEY environment variable not set") # Create temp directory for template temp_dir = tempfile.mkdtemp() template_path = os.path.join(temp_dir, 'draft.docx') # Extract from password-protected zip with zipfile.ZipFile('draft.zip', 'r') as zip_ref: zip_ref.extractall(temp_dir, pwd=zip_password.encode()) TEMPLATE_PATH = template_path return template_path def process_receipt(xml_file, user_name): """ Process uploaded XML receipt and generate ACT document Args: xml_file: Uploaded XML file from Gradio user_name: User name string (e.g., "ИП Пупкин Василий Алибабаевич") Returns: Path to generated DOCX file or error message """ if xml_file is None: return None, "⚠️ Please upload an XML receipt file" if not user_name or not user_name.strip(): return None, "⚠️ Please enter your name" user_name = user_name.strip() print('='*30) print(f'USER: {user_name}') print('='*30) try: # Extract template from zip template_path = extract_template() # Create temporary directory for processing with tempfile.TemporaryDirectory() as temp_dir: # Create esfs folder for XML files esfs_folder = os.path.join(temp_dir, 'esfs') os.makedirs(esfs_folder) # Create temp docs folder temp_docs_folder = os.path.join(temp_dir, '.temp_docs') os.makedirs(temp_docs_folder) # Copy uploaded XML file to esfs folder xml_path = os.path.join(esfs_folder, os.path.basename(xml_file.name)) shutil.copy(xml_file.name, xml_path) # Initialize components receipt_parser = ReceiptParser(esfs_folder) number_converter = NumberToWords() doc_processor = DocumentProcessor(template_path, user_name) doc_merger = DocumentMerger() # Parse receipts receipts_data = receipt_parser.get_all_receipt_data() if not receipts_data: return None, "⚠️ No receipt data found in XML file" # Process each receipt temp_files = [] for idx, receipt_data in enumerate(receipts_data, 1): # Convert price to words price_words = number_converter.convert(receipt_data['price']) # Prepare full data full_data = { 'contract_date': receipt_data['contract_date'], 'price': receipt_data['price'], 'price_words': price_words, 'today_date': receipt_data['today_date'] } # Process document doc = doc_processor.process_document(full_data) # Save to temporary folder temp_filename = os.path.join(temp_docs_folder, f"act_{idx:03d}.docx") doc.save(temp_filename) temp_files.append(temp_filename) # Merge all documents output_path = os.path.join(temp_dir, 'result.docx') doc_merger.merge_files(temp_files, output_path) # Create a permanent copy for download final_output = tempfile.NamedTemporaryFile( delete=False, suffix='.docx', prefix='act_' ) shutil.copy(output_path, final_output.name) success_msg = f"✅ Successfully processed {len(receipts_data)} receipt(s)" return final_output.name, success_msg except Exception as e: error_msg = f"❌ Error processing: {str(e)}" return None, error_msg # Create Gradio interface with gr.Blocks(title="ACT Maker - Acceptance Certificate Generator") as demo: gr.Markdown( """ # 📄 ACT Maker ### Automated Acceptance Certificate Generation from ESFS XML Receipts Upload an XML receipt file and enter your name to generate an acceptance certificate. """ ) with gr.Row(): with gr.Column(): xml_input = gr.File( label="📁 ESFS XML Receipt", file_types=[".xml"], type="filepath" ) user_name_input = gr.Textbox( label="👤 User Name", placeholder="e.g., ИП Иванов Иван Иванович", lines=1 ) submit_btn = gr.Button("🚀 Generate Certificate", variant="primary", size="lg") with gr.Column(): status_output = gr.Textbox( label="📊 Status", lines=2, interactive=False ) file_output = gr.File( label="📥 Download Document", interactive=False ) gr.Markdown( """ --- ### 📖 How to Use: 1. **Upload XML file** - ESFS receipt in XML format 2. **Enter your name** - Full name (e.g., "ИП Иванов Иван Иванович") 3. **Click "Generate Certificate"** - Document will be created automatically 4. **Download result** - Ready acceptance certificate in DOCX format ℹ️ If the XML file contains multiple receipts, they will be processed and merged into one document. """ ) # Connect the button to the processing function submit_btn.click( fn=process_receipt, inputs=[xml_input, user_name_input], outputs=[file_output, status_output] ) # Launch the app if __name__ == "__main__": demo.launch()