cuori/main.py
Isaak 2236de57ce
🔧✉️ Refactor Invoice Emailing Utility
- 🌐 Enhanced web interface for invoice emailing config management with GET/POST at '/data'.
- 📝 Refactored Flask app to specialize as an invoice emailing utility.
- 🔍 Improved read_yaml() to return data and error messages.
- 📤 Enhanced write_yaml() for better YAML file handling.
- 🛠️ Updated handle_data() to efficiently handle '/data' route with GET/POST methods.

Note: Excluded changes to imports and requires.
2023-12-23 00:12:43 +01:00

113 lines
4.0 KiB
Python

"""
Invoice Emailing Utility.
Provides a web interface for managing invoice emailing configurations.
Handles HTTP GET (view) and POST (update) at '/data' for configuration data, and serves the main app page at '/'.
Author: Isaak Buslovich
Date: 2023-12-21
"""
from flask import Flask, request, jsonify, send_from_directory
import yaml
from pathlib import Path
import logging
app = Flask(__name__, static_folder='.', static_url_path='')
logging.basicConfig(level=logging.INFO)
DATA_FILE = 'config.yaml'
def read_yaml():
"""
Reads data from YAML file specified by DATA_FILE. Returns a tuple containing the data and error message.
On success: Returns (data_dict, None), where data_dict contains 'email' and 'email_template'.
On file not found: Logs a message and returns ({'email': {}, 'email_template': ''}, None).
On error: Logs the specific error and returns (None, error_message), where error_message explains the issue.
"""
file_path = Path(DATA_FILE)
try:
if not file_path.is_file():
logging.info("YAML file not found. Returning empty data.")
return {'email': {}, 'email_template': ''}, None
with file_path.open() as file:
data = yaml.safe_load(file) or {}
return {
'email': data.get('email', {}),
'email_template': data.get('email_template', '')
}, None
except yaml.YAMLError as e:
logging.error(f"YAML Error: {e}", exc_info=True)
return None, f"YAML parsing error: {e}"
except IOError as e:
logging.error(f"IO Error: {e}", exc_info=True)
return None, f"File I/O error: {e}"
except Exception as e:
logging.error(f"Unexpected Error: {e}", exc_info=True)
return None, f"Unexpected error: {e}"
def write_yaml(email_data, email_template_data):
"""
Writes email and template data to the YAML file defined by DATA_FILE.
Args:
email_data (dict): Email configuration settings.
email_template_data (str): Email template content.
Returns:
tuple: (bool, str) indicating success status and an error message if any.
Raises:
Exception: Logs and returns error details upon failure.
"""
file_path = Path(DATA_FILE)
try:
with file_path.open('w') as file:
yaml.dump({
'email': email_data,
'email_template': email_template_data
}, file)
return True, None
except Exception as e:
logging.error(f"Error writing YAML file: {e}", exc_info=True)
return False, f"Error writing file: {e}"
@app.route('/data', methods=['GET', 'POST'])
def handle_data():
"""
Flask route handler function for '/data', accepting both GET and POST methods. - GET method: Reads and outputs
data from the YAML configuration file. In case of errors, it returns a 500 status code with an error message. -
POST method: Gets 'email' and 'email_template' data from the request, writes it to the YAML configuration file.
In case of write errors, it returns a 500 status code with an error message. Otherwise, it returns a message
stating the file was saved successfully with a 200 status code.
"""
if request.method == 'GET':
data, error = read_yaml()
if error:
return jsonify({'success': False, 'message': error}), 500
return jsonify(data), 200
elif request.method == 'POST':
email_data = request.json.get('email', {})
email_template_data = request.json.get('email_template', '')
success, error = write_yaml(email_data, email_template_data)
if error:
return jsonify({'success': False, 'message': error}), 500
return jsonify({'success': True, 'message': "File saved successfully"}), 200
@app.route('/')
def index():
"""
Serves the main index HTML page.
Returns:
HTML content of the main page.
"""
return send_from_directory('.', 'index.html')
if __name__ == '__main__':
app.run(debug=True)