122 lines
6.0 KiB
Python
122 lines
6.0 KiB
Python
from flask import Blueprint, render_template, request, jsonify, redirect, url_for, flash
|
|
from flask_login import login_required, current_user
|
|
from app.extensions import db
|
|
from app.models.project import Project
|
|
from app.models.aufmass import Aufmass
|
|
from app.models.position import Position
|
|
from app.models.lv import LVPosition
|
|
from app.services.license_service import check_user_module_access
|
|
|
|
modules_bp = Blueprint('modules', __name__)
|
|
|
|
@modules_bp.route('/<module_name>/formular')
|
|
@login_required
|
|
def formular(module_name):
|
|
if not check_user_module_access(current_user, module_name):
|
|
return 'Modul nicht freigeschaltet', 403
|
|
try:
|
|
mod = __import__(f'app.modules.{module_name}', fromlist=['get_formular_html'])
|
|
html = mod.get_formular_html()
|
|
aufmass_id = request.args.get('aufmass_id')
|
|
if aufmass_id and '<form' in html:
|
|
html = html.replace('</form>', f'<input type="hidden" name="aufmass_id" value="{aufmass_id}"></form>', 1)
|
|
return html
|
|
except (ImportError, AttributeError) as e:
|
|
return f'Modul {module_name} nicht gefunden: {e}', 404
|
|
|
|
@modules_bp.route('/<module_name>/berechnen', methods=['POST'])
|
|
@login_required
|
|
def berechnen(module_name):
|
|
if not check_user_module_access(current_user, module_name):
|
|
return jsonify({'error': 'Modul nicht freigeschaltet'}), 403
|
|
try:
|
|
mod = __import__(f'app.modules.{module_name}', fromlist=['berechne'])
|
|
form_data = request.form.to_dict()
|
|
aufmass_id = form_data.pop('aufmass_id', None)
|
|
sm_nr = form_data.pop('sm_nr', f'{module_name}_auto')
|
|
projekt_name = form_data.pop('projekt_name', f'{module_name} Berechnung')
|
|
result = mod.berechne(form_data)
|
|
|
|
# Use existing aufmass if aufmass_id provided
|
|
if aufmass_id:
|
|
aufmass = Aufmass.query.get(int(aufmass_id))
|
|
if not aufmass:
|
|
return '<div class="notification is-danger">Aufmaß nicht gefunden.<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'
|
|
project = Project.query.get(aufmass.project_id)
|
|
if not project or project.company_id != current_user.company_id:
|
|
return '<div class="notification is-danger">Kein Zugriff.<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'
|
|
locked, holder_id = aufmass.is_locked()
|
|
if locked and holder_id != current_user.id:
|
|
from app.models.user import User
|
|
holder = User.query.get(holder_id)
|
|
name = holder.full_name if holder else 'Unbekannt'
|
|
return f'<div class="notification is-danger">🔒 {name} bearbeitet dieses Aufmaß gerade.<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'
|
|
else:
|
|
project = Project.query.filter_by(company_id=current_user.company_id, sm_nr=sm_nr).first()
|
|
if not project:
|
|
project = Project(
|
|
company_id=current_user.company_id,
|
|
sm_nr=sm_nr,
|
|
bezeichnung=projekt_name,
|
|
status='aktiv',
|
|
erstellt_von=current_user.id,
|
|
)
|
|
db.session.add(project)
|
|
db.session.flush()
|
|
aufmass = Aufmass(project_id=project.id, name='Standard', typ='', sortierung=0, erstellt_von=current_user.id)
|
|
db.session.add(aufmass)
|
|
db.session.flush()
|
|
else:
|
|
aufmass = Aufmass.query.filter_by(project_id=project.id).order_by(Aufmass.sortierung).first()
|
|
if not aufmass:
|
|
aufmass = Aufmass(project_id=project.id, name='Standard', typ='', sortierung=0, erstellt_von=current_user.id)
|
|
db.session.add(aufmass)
|
|
db.session.flush()
|
|
|
|
max_sort = db.session.query(db.func.max(Position.sortierung)).filter_by(
|
|
aufmass_id=aufmass.id
|
|
).scalar() or 0
|
|
count = 0
|
|
for pos_data in result:
|
|
max_sort += 1
|
|
explicit_menge = pos_data.get('menge')
|
|
pos = Position(
|
|
project_id=project.id, aufmass_id=aufmass.id,
|
|
pos_nr=pos_data.get('pos_nr', ''),
|
|
sortierung=max_sort,
|
|
kurztext=pos_data.get('kurztext', ''),
|
|
einheit=pos_data.get('einheit', 'ST'),
|
|
einzelpreis=float(pos_data.get('einzelpreis', 0)),
|
|
menge=float(explicit_menge) if explicit_menge is not None else 0,
|
|
faktor=float(pos_data.get('faktor', 1)),
|
|
laenge=float(pos_data.get('laenge', 0)),
|
|
breite=float(pos_data.get('breite', 0)),
|
|
tiefe=float(pos_data.get('tiefe', 0)),
|
|
bemerkung=pos_data.get('bemerkung', ''),
|
|
gesamtpreis=0,
|
|
)
|
|
pos.berechne_menge()
|
|
if explicit_menge is not None:
|
|
pos.menge = float(explicit_menge)
|
|
pos.menge_hinten = pos.faktor * pos.menge
|
|
pos.gesamtpreis = pos.menge_hinten * pos.einzelpreis
|
|
db.session.add(pos)
|
|
count += 1
|
|
db.session.commit()
|
|
|
|
return f'''<div class="notification is-success">
|
|
<strong>{count} Positionen</strong> berechnet und ins Aufmaß übernommen.
|
|
<span class="is-pulled-right tag is-light is-info">Seite wird neu geladen...</span>
|
|
</div>
|
|
<script>
|
|
setTimeout(function() {{
|
|
var m = document.getElementById('modul-modal');
|
|
if (m) m.classList.remove('is-active');
|
|
location.reload();
|
|
}}, 1200);
|
|
</script>'''
|
|
except (ImportError, AttributeError) as e:
|
|
return f'<div class="notification is-danger">Modul-Fehler: {e}<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'
|
|
except Exception as e:
|
|
return f'<div class="notification is-danger">Fehler: {e}<br><button class="button is-small is-light mt-2" onclick="closeModulModal()">Schließen</button></div>'
|