Last active
July 23, 2025 22:19
-
-
Save elyssonmr/b23bbfa4345300597d649a9ae74f316c to your computer and use it in GitHub Desktop.
Código do artigo: https://blog.elyssonmr.com/posts/20250723_integration_file/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Install faker: pip install Faker | |
| from datetime import datetime, timezone, timedelta | |
| import random | |
| import time | |
| import json | |
| import os | |
| import sys | |
| from faker import Faker | |
| faker_factory = Faker() | |
| def get_invoice_data(): | |
| return { | |
| 'name': faker_factory.name(), | |
| 'address': faker_factory.address(), | |
| 'installation_identification': str( | |
| faker_factory.random_number(digits=8, fix_len=True) | |
| ), | |
| 'due_date': (datetime.now(tz=timezone.utc) + timedelta(days=5)).isoformat(), | |
| 'consumption': ( | |
| f'{faker_factory.random_number(digits=3)}.' | |
| f'{faker_factory.random_number(digits=2)}' | |
| ), | |
| 'email': faker_factory.email(True, domain='elyblog.com'), | |
| } | |
| def save_invoice_data(output_path, data): | |
| int_timestamp = str( | |
| datetime.now(tz=timezone.utc).timestamp() | |
| ).replace('.', '') | |
| file_name = os.path.join(output_path, f'invoice_{int_timestamp}.json') | |
| with open(file_name, mode='w', encoding='utf-8') as output_file: | |
| json.dump(data, fp=output_file, indent=2) | |
| return file_name | |
| if __name__ == '__main__': | |
| if len(sys.argv) == 1: | |
| print('You should provide a path in order to save the invoice data') | |
| sys.exit() | |
| output_path = os.path.abspath(sys.argv[1]) | |
| if not os.path.exists(output_path): | |
| print(f'Creating folder {output_path}') | |
| os.mkdir(output_path) | |
| print('Starting the invoice generator.\nYou can pause it using: CTRL+C (break)') | |
| try: | |
| while True: | |
| invoice_name = save_invoice_data(output_path, get_invoice_data()) | |
| print(f'Invoice: {invoice_name} generated') | |
| time.sleep(random.random() * 2) | |
| except KeyboardInterrupt: | |
| print('Stopping the generator') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>ElyssonMR's Blog Consumption Invoice</title> | |
| <style> | |
| body { | |
| font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| color: #333; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| width: 80%; | |
| margin: 0 auto; | |
| background-color: #fff; | |
| padding: 30px; | |
| border: 1px solid #eee; | |
| box-shadow: 0 0 10px rgba(0, 0, 0, 0.05); | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 40px; | |
| border-bottom: 2px solid #eee; | |
| padding-bottom: 20px; | |
| } | |
| .header h1 { | |
| color: #4CAF50; /* A pleasant green for the title */ | |
| margin: 0; | |
| font-size: 2em; | |
| } | |
| .section { | |
| margin-bottom: 30px; | |
| } | |
| .section h2 { | |
| color: #555; | |
| border-bottom: 1px solid #eee; | |
| padding-bottom: 5px; | |
| margin-bottom: 15px; | |
| } | |
| .data-item { | |
| margin-bottom: 10px; | |
| } | |
| .data-item strong { | |
| display: inline-block; | |
| width: 150px; /* Aligning labels */ | |
| color: #666; | |
| } | |
| .footer { | |
| text-align: center; | |
| margin-top: 50px; | |
| font-size: 0.9em; | |
| color: #777; | |
| border-top: 1px solid #eee; | |
| padding-top: 20px; | |
| } | |
| /* Basic table styling for potential future use or structured data */ | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| margin-top: 20px; | |
| } | |
| th, td { | |
| border: 1px solid #ddd; | |
| padding: 8px; | |
| text-align: left; | |
| } | |
| th { | |
| background-color: #f2f2f2; | |
| color: #555; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1>Consumption Report / Invoice</h1> | |
| </div> | |
| <div class="section"> | |
| <h2>Customer Information</h2> | |
| <div class="data-item"> | |
| <strong>Name:</strong> {{ name }} | |
| </div> | |
| <div class="data-item"> | |
| <strong>Address:</strong> {{ address }} | |
| </div> | |
| </div> | |
| <div class="section"> | |
| <h2>Installation Details</h2> | |
| <div class="data-item"> | |
| <strong>Installation ID:</strong> {{ installation_identification }} | |
| </div> | |
| <div class="data-item"> | |
| <strong>Due Date:</strong> {{ due_date }} | |
| </div> | |
| </div> | |
| <div class="section"> | |
| <h2>Consumption Details</h2> | |
| <div class="data-item"> | |
| <strong>Consumption:</strong> {{ consumption }} kWh | |
| </div> | |
| </div> | |
| <div class="footer"> | |
| <p>Thank you for your prompt payment.</p> | |
| <p>Generated by Google Gemini for ElyssonMR's Blog</p> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Install faker: pip install weasyprint Jinja2 | |
| from datetime import datetime, timezone | |
| import time | |
| import json | |
| import os | |
| import sys | |
| from jinja2 import Environment, FileSystemLoader | |
| from weasyprint import HTML | |
| templates = Environment(loader=FileSystemLoader('.')) | |
| def get_invoices(input_path): | |
| invoices = [] | |
| for invoice in os.listdir(input_path)[:5]: | |
| invoice_path = os.path.join(input_path, invoice) | |
| if os.path.isfile(invoice_path): | |
| invoices.append(invoice_path) | |
| return invoices | |
| def read_invoice_data(invoice_path): | |
| with open(invoice_path, encoding='utf-8') as input_file: | |
| return json.load(input_file) | |
| def create_pdf(invoice_data): | |
| template = templates.get_template('02_invoice_template.html') | |
| html_content = template.render(invoice_data) | |
| return HTML(string=html_content).write_pdf() | |
| def save_pdf_file(output_path, data, client_email): | |
| int_timestamp = str( | |
| datetime.now(tz=timezone.utc).timestamp() | |
| ).replace('.', '') | |
| file_name = os.path.join( | |
| output_path, | |
| f'invoice_{int_timestamp}_{client_email}.pdf' | |
| ) | |
| with open(file_name, mode='wb') as output_file: | |
| output_file.write(data) | |
| return file_name | |
| if __name__ == '__main__': | |
| if len(sys.argv) < 3: | |
| print('You should provide a path in order to read the invoice data and a path to save the generated PDF') | |
| sys.exit() | |
| input_path = os.path.abspath(sys.argv[1]) | |
| output_path = os.path.abspath(sys.argv[2]) | |
| if not os.path.exists(input_path): | |
| print('Input path does not exist, make sure to run the generator application') | |
| sys.exit() | |
| if not os.path.exists(output_path): | |
| print(f'Creating output folder: {output_path}') | |
| os.mkdir(output_path) | |
| print('Starting the PDF Generator.\nYou can pause it using: CTRL+C (break)') | |
| try: | |
| while True: | |
| invoices = get_invoices(input_path) | |
| if not invoices: | |
| print( | |
| 'No invoices to process. Checking again in 5 seconds' | |
| ) | |
| time.sleep(5) | |
| continue | |
| print(f'Found {len(invoices)} to process') | |
| print('=' * 20) | |
| for invoice in invoices: | |
| print(f'Reading Invoice Data from: {invoice}') | |
| invoice_data = read_invoice_data( | |
| os.path.join(input_path,invoice) | |
| ) | |
| print('Processing PDF') | |
| pdf_content = create_pdf(invoice_data) | |
| invoice_name = save_pdf_file( | |
| output_path, pdf_content, invoice_data['email'] | |
| ) | |
| print(f'PDF: {invoice_name} generated') | |
| os.remove(invoice) | |
| print('Invoice Removed\n') | |
| print('=' * 20) | |
| except KeyboardInterrupt: | |
| print('Stopping the generator') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import random | |
| import time | |
| import os | |
| import sys | |
| import re | |
| def get_pdfs(input_path): | |
| invoices = [] | |
| for invoice in os.listdir(input_path): | |
| invoice_path = os.path.join(input_path, invoice) | |
| if os.path.isfile(invoice_path): | |
| invoices.append(invoice_path) | |
| return invoices | |
| def extract_email(pdf_path): | |
| results = re.match(r'^.+invoice_\d+_(?P<email>.+)\.pdf$', pdf_path) | |
| if results: | |
| return results.group('email') | |
| def send_pdf(pdf, email): | |
| # Fake sending PDF trough email | |
| time.sleep(random.random()) | |
| if __name__ == '__main__': | |
| if len(sys.argv) == 1: | |
| print( | |
| 'You should provide a path in order to ' | |
| 'read the generated PDFs' | |
| ) | |
| sys.exit() | |
| input_path = os.path.abspath(sys.argv[1]) | |
| if not os.path.exists(input_path): | |
| print( | |
| 'Input path does not exist, ' | |
| 'make sure to run the PDF generator application' | |
| ) | |
| sys.exit() | |
| print( | |
| 'Starting the email sender.' | |
| '\nYou can pause it using: CTRL+C (break)' | |
| ) | |
| try: | |
| while True: | |
| pdfs = get_pdfs(input_path) | |
| if len(pdfs) == 0: | |
| print( | |
| 'There is no PDF to send. Checking again in 3 seconds' | |
| ) | |
| time.sleep(3) | |
| continue | |
| print(f'Sending {len(pdfs)} emails with the PDF file') | |
| print('=' * 20) | |
| for pdf in pdfs: | |
| email = extract_email(pdf) | |
| print(f'Sending PDF to {email}') | |
| send_pdf(pdf, email) | |
| print('Email Sent!!') | |
| os.remove(pdf) | |
| print('=' * 20) | |
| except KeyboardInterrupt: | |
| print('Stopping the generator') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pip install Faker weasyprint Jinja2 | |
| python 01_data_producer.py invoice_data | |
| python 02_pdf_writer.py invoice_data pdf_files | |
| python 03_email_sender.py pdf_files |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment