feat: add email service and appointment management module with configuration settings

This commit is contained in:
2026-05-29 15:38:22 +02:00
parent d722b5a774
commit a98f3751e9
7 changed files with 229 additions and 29 deletions
-8
View File
@@ -18,14 +18,6 @@ Collection Structure:
- Optional fields: Images, Filter, Filter2, Filter3, Anschaffungsjahr, Anschaffungskosten, Code_4
- Status fields: Verfuegbar, User (if currently borrowed)
"""
'''
Copyright 2025-2026 AIIrondev
Licensed under the Inventarsystem EULA (Endbenutzer-Lizenzvertrag).
See Legal/LICENSE for the full license text.
Unauthorized commercial use, SaaS hosting, or removal of branding is prohibited.
For commercial licensing inquiries: https://github.com/AIIrondev
'''
from bson.objectid import ObjectId
import datetime
import Web.modules.database.settings as cfg
+17 -20
View File
@@ -166,32 +166,18 @@ def _get_int_env(name, default):
def get_version():
# Prefer an explicit release marker if present (created by release process).
project_root = os.path.abspath(os.path.join(BASE_DIR, '..', '..', '..'))
release_file = os.path.join(project_root, '.release-version')
release_file = os.path.join(project_root, '.docker-build.env')
try:
if os.path.isfile(release_file):
with open(release_file, 'r', encoding='utf-8') as f:
val = f.read().strip()
if val:
return val
var = f.readline()
for i in var:
i = i.split(":")
i.pop[0]
return str(i)
except Exception:
pass
# Fallback to .docker-build.env (legacy behaviour)
env_path = os.path.join(project_root, '.docker-build.env')
try:
with open(env_path, 'r', encoding='utf-8') as f:
for l in f:
if l.startswith('INVENTAR_APP_IMAGE='):
return l.split(':', 1)[1].strip()
except Exception:
pass
# Final fallback: use config.json value or packaged default
try:
return _get(_conf, ['ver'], DEFAULTS.get('version', '0.0.0'))
except Exception:
return DEFAULTS.get('version', '0.0.0')
# Expose settings
APP_VERSION = get_version()
DEBUG = _get_bool_env('INVENTAR_DEBUG', _get(_conf, ['dbg'], DEFAULTS['debug']))
@@ -230,6 +216,17 @@ SSL_ENABLED = _get(_conf, ['ssl', 'enabled'], DEFAULTS['ssl']['enabled'])
SSL_CERT = _get(_conf, ['ssl', 'cert'], DEFAULTS['ssl']['cert'])
SSL_KEY = _get(_conf, ['ssl', 'key'], DEFAULTS['ssl']['key'])
# Email settings
EMAIL_ENABLED = _get(_conf, ['email', 'enabled'], False)
EMAIL_SMTP_HOST = _get(_conf, ['email', 'smtp_host'], 'smtp.gmail.com')
EMAIL_SMTP_PORT = int(_get(_conf, ['email', 'smtp_port'], 587))
EMAIL_USE_TLS = bool(_get(_conf, ['email', 'use_tls'], True))
EMAIL_USERNAME = _get(_conf, ['email', 'username'], '')
EMAIL_PASSWORD = _get(_conf, ['email', 'password'], '')
EMAIL_FROM_ADDRESS = _get(_conf, ['email', 'from_address'], EMAIL_USERNAME)
EMAIL_DEFAULT_SENDER_NAME = _get(_conf, ['email', 'default_sender_name'], 'Inventarsystem')
EMAIL_TIMEOUT_SECONDS = int(_get(_conf, ['email', 'timeout_seconds'], 30))
# School periods
SCHOOL_PERIODS = _get(_conf, ['schoolPeriods'], DEFAULTS['schoolPeriods'])
SCHOOL_INFO_DEFAULT = _get(_conf, ['school'], DEFAULTS['school'])
+110
View File
@@ -0,0 +1,110 @@
"""
Apointment Managment
=========================
This module manages appointments in the database. It provides comprehensive
functionality for creating, updating, retrieving appointments items.
Key Features:
- Creating and updating appointments
- Retrieving items by ID
- Managing time slots
- client retrival
Collection Structure:
- appointments:
- Required fields: user, start_date, end_date, daytime, slots, slot_time
- Optional fields: Images, Filter, Filter2, Filter3, Anschaffungsjahr, Anschaffungskosten, Code_4
- Status fields: slots_used_by
"""
import Web.modules.database.settings as cfg
from Web.modules.database.settings import MongoClient
from bson.objectid import ObjectId
import datetime
def _active_record_query(extra_query=None):
"""Build a query that excludes logically deleted records."""
base_query = {'Deleted': {'$ne': True}}
if extra_query:
base_query.update(extra_query)
return base_query
def add(date_start: str, date_end: str, time_span: list, slots: int, slot_lenght: int, user: str, mail: list=[], note:str=""):
try:
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
db = client[cfg.MONGODB_DB]
items = db['appointments']
item = {
'date_start': date_start,
'date_end': date_end,
'time_span': time_span,
'slots': slots,
'slot_lenght': slot_lenght,
'user': user,
'mail': mail,
'note': note,
'slots_booked': [], # -> [(start_time, name), ...]the list gets there indexes as the slot 1-defined so is can be counted without an extra variable
'Created': datetime.datetime.now(),
'LastUpdated': datetime.datetime.now()
}
result = items.insert_one(item)
return result.inserted_id
except Exception as e:
print(f"Exception accured: {e}")
def get_item(id):
"""
Retrieve a specific appointment by its ID.
Args:
id (str): ID of the appointsment to retrieve
Returns:
dict: The appointment document or None if not found
"""
try:
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
db = client[cfg.MONGODB_DB]
items = db['appointments']
item = items.find_one(_active_record_query({'_id': ObjectId(id)}))
client.close()
return item
except Exception as e:
print(f"Error retrieving item: {e}")
return None
def update(id,slots_used: list):
"""
Update an existing appointment.
Args:
id (str): ID of the item to update
Returns:
bool: True if successful, False otherwise
"""
try:
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
db = client[cfg.MONGODB_DB]
items = db['appointments']
update_data = {
'slots_booked': [slots_used],
'LastUpdated': datetime.datetime.now()
}
result = items.update_one(
{'_id': ObjectId(id)},
{'$set': update_data}
)
client.close()
return result.modified_count > 0
except Exception as e:
print(f"Error updating item: {e}")
return False