lexoffice.py added
This commit is contained in:
parent
8bef4f81e0
commit
59ca900a14
2
.gitignore
vendored
2
.gitignore
vendored
@ -294,3 +294,5 @@ $RECYCLE.BIN/
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Sensitive details
|
||||
config.yaml
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
Rechnungsnummer;Email;Anrede
|
||||
RE357891;isaak.buslovich@trocknerheld.de;Isaak Trocknerheld
|
||||
RE255111;fws-rs@vielhuber.eu;Sehr geehrter Herr Vielhuber
|
||||
|
||||
|
58
app/lexoffice.py
Normal file
58
app/lexoffice.py
Normal file
@ -0,0 +1,58 @@
|
||||
"""
|
||||
Module: lexoffice.py
|
||||
Description: Provides an interface to interact with the Lexoffice API.
|
||||
This module enables operations such as retrieving invoice details from Lexoffice,
|
||||
making it easier to integrate Lexoffice API functionality into a Flask application.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import yaml
|
||||
import requests
|
||||
import logging
|
||||
|
||||
|
||||
class LexofficeAPI:
|
||||
"""Class to handle interactions with the Lexoffice API."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize with the Lexoffice API access token from a config file."""
|
||||
self.base_url = "https://api.lexoffice.io/v1"
|
||||
self.headers = {
|
||||
"Authorization": f"Bearer {self._load_api_token()}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json"
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _load_api_token() -> str:
|
||||
"""Load the API token from the config.yaml file."""
|
||||
config_path = Path(__file__).parent.parent / 'config.yaml'
|
||||
with config_path.open('r') as file:
|
||||
config = yaml.safe_load(file)
|
||||
return config['lexoffice']['api_token']
|
||||
|
||||
def get_invoice_total_gross_amount(self, invoice_id: str) -> float:
|
||||
"""
|
||||
Retrieve the total gross amount for a specific invoice.
|
||||
|
||||
Args:
|
||||
invoice_id (str): Unique identifier of the invoice.
|
||||
|
||||
Returns:
|
||||
float or None: Total gross amount of the invoice, or None if an error occurs.
|
||||
"""
|
||||
url = f"{self.base_url}/invoices/{invoice_id}"
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=self.headers)
|
||||
response.raise_for_status()
|
||||
return response.json().get('totalPrice', {}).get('totalGrossAmount')
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logging.error(f"Error fetching invoice: {e}")
|
||||
return None
|
||||
|
||||
# Usage example:
|
||||
# lexoffice_api = LexofficeAPI()
|
||||
# total_gross_amount = lexoffice_api.get_invoice_total_gross_amount('your_invoice_id')
|
||||
# print(total_gross_amount)
|
||||
@ -1,8 +1,10 @@
|
||||
from flask import render_template, redirect, url_for, current_app, render_template_string, request
|
||||
import os
|
||||
import csv
|
||||
|
||||
from app import app, htmx
|
||||
import logging
|
||||
|
||||
from app.lexoffice import LexofficeAPI
|
||||
|
||||
|
||||
def read_invoices_from_csv(csv_file_path):
|
||||
@ -10,10 +12,11 @@ def read_invoices_from_csv(csv_file_path):
|
||||
with open(csv_file_path, mode='r', encoding='utf-8') as file:
|
||||
return list(csv.DictReader(file, delimiter=';'))
|
||||
except FileNotFoundError:
|
||||
current_app.logger.error(f"CSV file not found at {csv_file_path}")
|
||||
logging.error(f"CSV file not found at {csv_file_path}")
|
||||
return []
|
||||
except csv.Error as e:
|
||||
current_app.logger.error(f"Error reading CSV file: {e}")
|
||||
return []
|
||||
logging.error(f"Error reading CSV file: {e}")
|
||||
return []
|
||||
|
||||
|
||||
@app.route('/load-invoices')
|
||||
@ -48,31 +51,46 @@ def buchhaltung():
|
||||
@app.route('/add-invoice', methods=['POST'])
|
||||
def add_invoice():
|
||||
csv_file_path = os.path.join(current_app.root_path, 'data', 'invoices.csv')
|
||||
|
||||
# Extract invoice data from form
|
||||
new_invoice = {
|
||||
'Rechnungsnummer': request.form['rechnungsnummer'],
|
||||
'Email': request.form['email'],
|
||||
'Anrede': request.form['anrede']
|
||||
'Anrede': request.form['anrede'],
|
||||
# Initialize 'Betrag' with a placeholder (to be updated)
|
||||
'Betrag': 'N/A'
|
||||
}
|
||||
|
||||
try:
|
||||
# Read the existing data
|
||||
# Fetch the total gross amount for the new invoice using LexofficeAPI
|
||||
lexoffice_api = LexofficeAPI('your_access_token') # Replace with actual access token
|
||||
total_gross_amount = lexoffice_api.get_invoice_total_gross_amount(new_invoice['Rechnungsnummer'])
|
||||
|
||||
# Update 'Betrag' in the new invoice data
|
||||
if total_gross_amount is not None:
|
||||
new_invoice['Betrag'] = total_gross_amount
|
||||
|
||||
# Read existing data from CSV
|
||||
with open(csv_file_path, 'r', newline='', encoding='utf-8') as csvfile:
|
||||
reader = csv.DictReader(csvfile, delimiter=';')
|
||||
fieldnames = reader.fieldnames
|
||||
if 'Betrag' not in fieldnames:
|
||||
fieldnames.append('Betrag')
|
||||
existing_data = list(reader)
|
||||
|
||||
# Add the new invoice at the beginning of the data
|
||||
existing_data.insert(0, new_invoice)
|
||||
|
||||
# Write the updated data back to the file
|
||||
# Write the updated data back to the CSV file
|
||||
with open(csv_file_path, 'w', newline='', encoding='utf-8') as csvfile:
|
||||
writer = csv.DictWriter(csvfile, fieldnames=fieldnames, delimiter=';')
|
||||
writer.writeheader()
|
||||
writer.writerows(existing_data)
|
||||
|
||||
return redirect(url_for('buchhaltung'))
|
||||
|
||||
except Exception as e:
|
||||
current_app.logger.error(f"Error updating CSV file: {e}")
|
||||
logging.error(f"Error updating CSV file: {e}")
|
||||
return "An error occurred while adding the invoice", 500
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/* Import Google Fonts */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
|
||||
|
||||
/* Root and Variable Definitions */
|
||||
:root {
|
||||
@ -17,7 +17,7 @@
|
||||
|
||||
/* Body and Global Styles */
|
||||
body {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-family: 'Inter', sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: var(--light-grey);
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
<th>Rechnungsnummer</th>
|
||||
<th>Email</th>
|
||||
<th>Anrede</th>
|
||||
<th>Betrag</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -13,6 +14,7 @@
|
||||
<td>{{ invoice['Rechnungsnummer'] }}</td>
|
||||
<td>{{ invoice['Email'] }}</td>
|
||||
<td>{{ invoice['Anrede'] }}</td>
|
||||
<td>{{ invoice['Betrag'] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@ -1 +1,3 @@
|
||||
flask~=2.2.5
|
||||
requests~=2.25.1
|
||||
pyyaml~=6.0.1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user