Initial commit – AufmaßCreater v2.35
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,51 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
LOCK_TIMEOUT = timedelta(minutes=2)
|
||||
|
||||
class Aufmass(db.Model):
|
||||
__tablename__ = 'aufmass'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
project_id = db.Column(db.Integer, db.ForeignKey('projekte.id'), nullable=False)
|
||||
name = db.Column(db.String(200), nullable=False, default='Standard')
|
||||
typ = db.Column(db.String(50), default='')
|
||||
status = db.Column(db.String(20), default='aktiv')
|
||||
sortierung = db.Column(db.Integer, default=0)
|
||||
bemerkung = db.Column(db.Text)
|
||||
erstellt_von = db.Column(db.Integer, db.ForeignKey('users.id'))
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
geaendert_am = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
locked_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
|
||||
locked_at = db.Column(db.DateTime, nullable=True)
|
||||
|
||||
positionen = db.relationship('Position', backref='aufmass_ref', lazy='dynamic',
|
||||
cascade='all, delete-orphan', order_by='Position.sortierung')
|
||||
|
||||
def is_locked(self):
|
||||
if not self.locked_by or not self.locked_at:
|
||||
return False, None
|
||||
if datetime.utcnow() - self.locked_at > LOCK_TIMEOUT:
|
||||
return False, None
|
||||
return True, self.locked_by
|
||||
|
||||
def try_lock(self, user_id):
|
||||
locked, holder = self.is_locked()
|
||||
if locked and holder != user_id:
|
||||
return False
|
||||
self.locked_by = user_id
|
||||
self.locked_at = datetime.utcnow()
|
||||
return True
|
||||
|
||||
def unlock(self):
|
||||
self.locked_by = None
|
||||
self.locked_at = None
|
||||
|
||||
def refresh_lock(self, user_id):
|
||||
if self.locked_by == user_id:
|
||||
self.locked_at = datetime.utcnow()
|
||||
return True
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Aufmass {self.name} @ {self.project_id}>'
|
||||
@@ -0,0 +1,17 @@
|
||||
from datetime import datetime
|
||||
from app.extensions import db
|
||||
|
||||
class AufmassHistory(db.Model):
|
||||
__tablename__ = 'aufmass_history'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
aufmass_id = db.Column(db.Integer, db.ForeignKey('aufmass.id'), nullable=False, index=True)
|
||||
position_id = db.Column(db.Integer, db.ForeignKey('positionen.id', ondelete='SET NULL'), nullable=True)
|
||||
changed_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
changed_at = db.Column(db.DateTime, default=datetime.utcnow, index=True)
|
||||
action = db.Column(db.String(10), nullable=False)
|
||||
description = db.Column(db.String(500), nullable=True)
|
||||
diff = db.Column(db.Text, nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f'<AufmassHistory {self.id} {self.action} @ {self.changed_at}>'
|
||||
@@ -0,0 +1,12 @@
|
||||
from app.extensions import db
|
||||
|
||||
class AufmassTyp(db.Model):
|
||||
__tablename__ = 'aufmass_typen'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(100), nullable=False)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=True)
|
||||
sortierung = db.Column(db.Integer, default=0)
|
||||
|
||||
def __repr__(self):
|
||||
return f'<AufmassTyp {self.name}>'
|
||||
@@ -0,0 +1,29 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class Company(db.Model):
|
||||
__tablename__ = 'companies'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(200), nullable=False)
|
||||
slug = db.Column(db.String(100), unique=True, nullable=False)
|
||||
strasse = db.Column(db.String(200))
|
||||
house_number = db.Column(db.String(20))
|
||||
plz = db.Column(db.String(10))
|
||||
ort = db.Column(db.String(100))
|
||||
telefon = db.Column(db.String(50))
|
||||
email = db.Column(db.String(200))
|
||||
logo = db.Column(db.String(500))
|
||||
aktiv = db.Column(db.Boolean, default=True)
|
||||
evergabe_aktiviert = db.Column(db.Boolean, default=False)
|
||||
evergabe_benutzer = db.Column(db.String(200))
|
||||
evergabe_passwort = db.Column(db.String(300))
|
||||
evergabe_name = db.Column(db.String(200))
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
users = db.relationship('User', backref='company', lazy='dynamic')
|
||||
licenses = db.relationship('License', backref='company', lazy='dynamic')
|
||||
projekte = db.relationship('Project', backref='company', lazy='dynamic')
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Company {self.name}>'
|
||||
@@ -0,0 +1,14 @@
|
||||
from app.extensions import db
|
||||
|
||||
class CompanyModule(db.Model):
|
||||
__tablename__ = 'company_modules'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=False)
|
||||
module_id = db.Column(db.Integer, db.ForeignKey('modules.id'), nullable=False)
|
||||
aktiv = db.Column(db.Boolean, default=True)
|
||||
|
||||
company = db.relationship('Company', backref='company_module_list')
|
||||
module = db.relationship('Module', backref='company_assignments')
|
||||
|
||||
__table_args__ = (db.UniqueConstraint('company_id', 'module_id'),)
|
||||
@@ -0,0 +1,20 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class Contract(db.Model):
|
||||
__tablename__ = 'contracts'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=False)
|
||||
name = db.Column(db.String(300), nullable=False)
|
||||
belegnummer = db.Column(db.String(100))
|
||||
beleg_datum = db.Column(db.Date)
|
||||
laufzeit_start = db.Column(db.Date)
|
||||
laufzeit_ende = db.Column(db.Date)
|
||||
status = db.Column(db.String(50), default='NEU') # NEU, Zur Prüfung, Angenommen
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
projekte = db.relationship('Project', backref='contract', lazy='dynamic')
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Contract {self.name}>'
|
||||
@@ -0,0 +1,62 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class CustomModule(db.Model):
|
||||
__tablename__ = 'custom_modules'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=True)
|
||||
original_template_id = db.Column(db.Integer, db.ForeignKey('custom_modules.id'), nullable=True)
|
||||
name = db.Column(db.String(200), nullable=False)
|
||||
description = db.Column(db.Text, default='')
|
||||
kategorie = db.Column(db.String(50), default='allgemein')
|
||||
icon = db.Column(db.String(50), default='🔧')
|
||||
form_json = db.Column(db.Text, default='[]')
|
||||
rules_json = db.Column(db.Text, default='[]')
|
||||
is_template = db.Column(db.Boolean, default=False)
|
||||
sort_index = db.Column(db.Integer, default=0)
|
||||
is_active = db.Column(db.Boolean, default=True)
|
||||
created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
company = db.relationship('Company', backref='custom_modules', foreign_keys=[company_id])
|
||||
template = db.relationship('CustomModule', backref='copies', remote_side=[id])
|
||||
creator = db.relationship('User', backref='created_custom_modules', foreign_keys=[created_by])
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'company_id': self.company_id,
|
||||
'original_template_id': self.original_template_id,
|
||||
'name': self.name,
|
||||
'description': self.description,
|
||||
'kategorie': self.kategorie,
|
||||
'icon': self.icon,
|
||||
'is_template': self.is_template,
|
||||
'sort_index': self.sort_index,
|
||||
'is_active': self.is_active,
|
||||
'created_by': self.created_by,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
'updated_at': self.updated_at.isoformat() if self.updated_at else None,
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<CustomModule {self.name} ({"template" if self.is_template else "company"})>'
|
||||
|
||||
|
||||
class CustomModuleAssignment(db.Model):
|
||||
__tablename__ = 'custom_module_assignments'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
module_id = db.Column(db.Integer, db.ForeignKey('custom_modules.id'), nullable=False)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
can_edit = db.Column(db.Boolean, default=False)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
module = db.relationship('CustomModule', backref='assignments')
|
||||
user = db.relationship('User', backref='custom_module_assignments')
|
||||
|
||||
__table_args__ = (
|
||||
db.UniqueConstraint('module_id', 'user_id', name='uq_module_user'),
|
||||
)
|
||||
@@ -0,0 +1,59 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
import hashlib, secrets
|
||||
|
||||
def _generate_uid(company_name):
|
||||
raw = f"{company_name}-{secrets.token_hex(6)}"
|
||||
return hashlib.sha256(raw.encode()).hexdigest()[:12]
|
||||
|
||||
class License(db.Model):
|
||||
__tablename__ = 'licenses'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=False)
|
||||
uid = db.Column(db.String(64), unique=True, nullable=False)
|
||||
max_mitarbeiter = db.Column(db.Integer, default=5)
|
||||
max_module_slots = db.Column(db.Integer, default=5)
|
||||
unlimited_users = db.Column(db.Boolean, default=False)
|
||||
unlimited_modules = db.Column(db.Boolean, default=False)
|
||||
aktiv = db.Column(db.Boolean, default=True)
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
modules = db.relationship('LicenseModule', backref='license', lazy='dynamic', cascade='all, delete-orphan')
|
||||
|
||||
@property
|
||||
def used_users(self):
|
||||
from app.models.user import User
|
||||
return User.query.filter_by(company_id=self.company_id).count()
|
||||
|
||||
@property
|
||||
def used_module_slots(self):
|
||||
from app.models.user_module import UserModulePermission
|
||||
from app.models.user import User
|
||||
return db.session.query(UserModulePermission.id).join(User, UserModulePermission.user_id==User.id)\
|
||||
.filter(User.company_id==self.company_id, UserModulePermission.aktiv==True).count()
|
||||
|
||||
def user_slots_display(self):
|
||||
if self.unlimited_users: return '\u221e'
|
||||
return f'{self.used_users} / {self.max_mitarbeiter}'
|
||||
|
||||
def module_slots_display(self):
|
||||
if self.unlimited_modules: return '\u221e'
|
||||
return f'{self.used_module_slots} / {self.max_module_slots}'
|
||||
|
||||
@staticmethod
|
||||
def generate_uid(company_name):
|
||||
return _generate_uid(company_name)
|
||||
|
||||
def __repr__(self):
|
||||
return f'<License {self.uid}>'
|
||||
|
||||
class LicenseModule(db.Model):
|
||||
__tablename__ = 'license_modules'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
license_id = db.Column(db.Integer, db.ForeignKey('licenses.id'), nullable=False)
|
||||
module_id = db.Column(db.Integer, db.ForeignKey('modules.id'), nullable=False)
|
||||
aktiv = db.Column(db.Boolean, default=True)
|
||||
|
||||
module = db.relationship('Module', backref='license_assignments')
|
||||
@@ -0,0 +1,44 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class LVPosition(db.Model):
|
||||
__tablename__ = 'lv_positionen'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=False)
|
||||
contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=True)
|
||||
lv_name = db.Column(db.String(200), nullable=False)
|
||||
pos_nr = db.Column(db.String(50), nullable=False)
|
||||
order_index = db.Column(db.Integer, default=0)
|
||||
kurztext = db.Column(db.String(300))
|
||||
langtext = db.Column(db.Text)
|
||||
einheit = db.Column(db.String(10), default='ST')
|
||||
einzelpreis = db.Column(db.Float, default=0.0)
|
||||
gruppe = db.Column(db.String(100))
|
||||
rsa = db.Column(db.String(20))
|
||||
abschnitt = db.Column(db.String(100))
|
||||
notiz = db.Column(db.Text)
|
||||
favorite = db.Column(db.Boolean, default=False)
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
__table_args__ = (
|
||||
db.UniqueConstraint('company_id', 'lv_name', 'pos_nr', name='uq_lv_position'),
|
||||
)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'lv_name': self.lv_name,
|
||||
'pos_nr': self.pos_nr,
|
||||
'kurztext': self.kurztext,
|
||||
'langtext': self.langtext,
|
||||
'einheit': self.einheit,
|
||||
'einzelpreis': self.einzelpreis,
|
||||
'gruppe': self.gruppe,
|
||||
'rsa': self.rsa,
|
||||
'abschnitt': self.abschnitt,
|
||||
'favorite': self.favorite,
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<LV {self.lv_name} | {self.pos_nr}>'
|
||||
@@ -0,0 +1,16 @@
|
||||
from app.extensions import db
|
||||
|
||||
class Module(db.Model):
|
||||
__tablename__ = 'modules'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
name = db.Column(db.String(100), unique=True, nullable=False)
|
||||
titel = db.Column(db.String(200), nullable=False)
|
||||
kategorie = db.Column(db.String(100))
|
||||
icon = db.Column(db.String(20), default='📦')
|
||||
beschreibung = db.Column(db.Text)
|
||||
standard = db.Column(db.Boolean, default=False) # immer verfügbar
|
||||
sortierung = db.Column(db.Integer, default=0)
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Module {self.name}>'
|
||||
@@ -0,0 +1,78 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class Position(db.Model):
|
||||
__tablename__ = 'positionen'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
project_id = db.Column(db.Integer, db.ForeignKey('projekte.id'), nullable=False)
|
||||
aufmass_id = db.Column(db.Integer, db.ForeignKey('aufmass.id'), nullable=True)
|
||||
lv_position_id = db.Column(db.Integer, db.ForeignKey('lv_positionen.id'), nullable=True)
|
||||
pos_nr = db.Column(db.String(50), nullable=False)
|
||||
sortierung = db.Column(db.Integer, default=0)
|
||||
rsa = db.Column(db.String(20))
|
||||
abschnitt = db.Column(db.String(100))
|
||||
kurztext = db.Column(db.String(300))
|
||||
langtext = db.Column(db.Text)
|
||||
einheit = db.Column(db.String(10), default='ST')
|
||||
einzelpreis = db.Column(db.Float, default=0.0)
|
||||
menge = db.Column(db.Float, default=0.0)
|
||||
gesamtpreis = db.Column(db.Float, default=0.0)
|
||||
faktor = db.Column(db.Float, default=1.0)
|
||||
laenge = db.Column(db.Float, default=0.0)
|
||||
breite = db.Column(db.Float, default=0.0)
|
||||
tiefe = db.Column(db.Float, default=0.0)
|
||||
formel_typ = db.Column(db.String(10), default='standard')
|
||||
formel = db.Column(db.String(300))
|
||||
bemerkung = db.Column(db.Text)
|
||||
menge_hinten = db.Column(db.Float, default=0.0)
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
def berechne_menge(self, recalc_hinten=True, skip_menge_recalc=False):
|
||||
if not skip_menge_recalc:
|
||||
if self.formel_typ == 'frei':
|
||||
if self.formel:
|
||||
from app.services.formel_rechner import berechne_formel
|
||||
try:
|
||||
self.menge = berechne_formel(self.formel)
|
||||
except Exception:
|
||||
self.menge = 0
|
||||
else:
|
||||
self.menge = 0
|
||||
elif self.einheit == 'ST':
|
||||
self.menge = self.faktor * 1
|
||||
elif self.einheit == 'M':
|
||||
self.menge = self.laenge
|
||||
elif self.einheit == 'M2':
|
||||
self.menge = self.laenge * self.breite
|
||||
elif self.einheit == 'M3':
|
||||
self.menge = self.laenge * self.breite * self.tiefe
|
||||
else:
|
||||
self.menge = self.laenge
|
||||
if recalc_hinten:
|
||||
self.menge_hinten = self.faktor * self.menge
|
||||
self.gesamtpreis = self.menge_hinten * self.einzelpreis
|
||||
return self.menge
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'pos_nr': self.pos_nr,
|
||||
'sortierung': self.sortierung,
|
||||
'rsa': self.rsa,
|
||||
'kurztext': self.kurztext,
|
||||
'langtext': self.langtext,
|
||||
'einheit': self.einheit,
|
||||
'einzelpreis': self.einzelpreis,
|
||||
'menge': self.menge,
|
||||
'gesamtpreis': self.gesamtpreis,
|
||||
'faktor': self.faktor,
|
||||
'laenge': self.laenge,
|
||||
'breite': self.breite,
|
||||
'tiefe': self.tiefe,
|
||||
'bemerkung': self.bemerkung,
|
||||
'menge_hinten': self.menge_hinten,
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Position {self.pos_nr} @ {self.project_id}>'
|
||||
@@ -0,0 +1,37 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class Project(db.Model):
|
||||
__tablename__ = 'projekte'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=False)
|
||||
contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=True)
|
||||
sm_nr = db.Column(db.String(100), nullable=False, default='')
|
||||
bezeichnung = db.Column(db.String(300))
|
||||
baustelle = db.Column(db.String(300))
|
||||
vertrag = db.Column(db.String(200))
|
||||
abruf_nr = db.Column(db.String(100))
|
||||
lv_name = db.Column(db.String(200))
|
||||
datum_start = db.Column(db.Date)
|
||||
datum_ende = db.Column(db.Date)
|
||||
ansprechpartner_vorname = db.Column(db.String(100))
|
||||
ansprechpartner_nachname = db.Column(db.String(100))
|
||||
ansprechpartner_tel = db.Column(db.String(50))
|
||||
ansprechpartner_email = db.Column(db.String(200))
|
||||
bauabschnitt = db.Column(db.String(200))
|
||||
datum = db.Column(db.Date)
|
||||
ev_details_id = db.Column(db.String(50))
|
||||
status = db.Column(db.String(20), default='aktiv')
|
||||
erstellt_von = db.Column(db.Integer, db.ForeignKey('users.id'))
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
geaendert_am = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
positionen = db.relationship('Position', backref='project', lazy='dynamic',
|
||||
cascade='all, delete-orphan', order_by='Position.sortierung')
|
||||
aufmass_liste = db.relationship('Aufmass', backref='aufmass_project',
|
||||
cascade='all, delete-orphan',
|
||||
order_by='Aufmass.sortierung')
|
||||
|
||||
def __repr__(self):
|
||||
return f'<Project {self.sm_nr}>'
|
||||
@@ -0,0 +1,17 @@
|
||||
from app.extensions import db
|
||||
|
||||
class ProjectAccess(db.Model):
|
||||
__tablename__ = 'project_access'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
project_id = db.Column(db.Integer, db.ForeignKey('projekte.id'), nullable=False)
|
||||
zugriff = db.Column(db.String(20), default='lesen')
|
||||
|
||||
user = db.relationship('User', backref='project_access_list')
|
||||
project = db.relationship('Project', backref='user_access_list')
|
||||
|
||||
__table_args__ = (db.UniqueConstraint('user_id', 'project_id'),)
|
||||
|
||||
def __repr__(self):
|
||||
return f'<ProjectAccess u={self.user_id} p={self.project_id} {self.zugriff}>'
|
||||
@@ -0,0 +1,24 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
|
||||
class Settings(db.Model):
|
||||
__tablename__ = 'settings'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
key = db.Column(db.String(100), unique=True, nullable=False)
|
||||
value = db.Column(db.Text)
|
||||
|
||||
@classmethod
|
||||
def get(cls, key, default=None):
|
||||
s = cls.query.filter_by(key=key).first()
|
||||
return s.value if s else default
|
||||
|
||||
@classmethod
|
||||
def set(cls, key, value):
|
||||
s = cls.query.filter_by(key=key).first()
|
||||
if s:
|
||||
s.value = value
|
||||
else:
|
||||
s = cls(key=key, value=value)
|
||||
db.session.add(s)
|
||||
db.session.commit()
|
||||
@@ -0,0 +1,80 @@
|
||||
from app.extensions import db, login_manager
|
||||
from flask_login import UserMixin
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from datetime import datetime
|
||||
|
||||
class User(UserMixin, db.Model):
|
||||
__tablename__ = 'users'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
company_id = db.Column(db.Integer, db.ForeignKey('companies.id'), nullable=True)
|
||||
email = db.Column(db.String(200), unique=True, nullable=False)
|
||||
password_hash = db.Column(db.String(300), nullable=False)
|
||||
vorname = db.Column(db.String(100))
|
||||
nachname = db.Column(db.String(100))
|
||||
rolle = db.Column(db.String(20), default='mitarbeiter')
|
||||
aktiv = db.Column(db.Boolean, default=True)
|
||||
font_size = db.Column(db.String(10), default='1')
|
||||
profile_image = db.Column(db.String(255), nullable=True)
|
||||
letzter_login = db.Column(db.DateTime)
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
darf_projekte_anlegen = db.Column(db.Boolean, default=False)
|
||||
darf_lv_verwalten = db.Column(db.Boolean, default=False)
|
||||
darf_preise_sehen = db.Column(db.Boolean, default=False)
|
||||
darf_aufmass_verwalten = db.Column(db.Boolean, default=False)
|
||||
darf_evergabe_nutzen = db.Column(db.Boolean, default=False)
|
||||
darf_kopfdaten_holen = db.Column(db.Boolean, default=False)
|
||||
darf_aufmass_uebertragen = db.Column(db.Boolean, default=False)
|
||||
hidden_modules = db.Column(db.Text, default='[]')
|
||||
|
||||
def get_hidden_modules(self):
|
||||
import json
|
||||
try:
|
||||
return json.loads(self.hidden_modules or '[]')
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
return []
|
||||
|
||||
def set_hidden_modules(self, val):
|
||||
import json
|
||||
self.hidden_modules = json.dumps(val, ensure_ascii=False)
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
return f"{self.vorname or ''} {self.nachname or ''}".strip() or self.email
|
||||
|
||||
def set_password(self, password):
|
||||
self.password_hash = generate_password_hash(password)
|
||||
|
||||
def check_password(self, password):
|
||||
return check_password_hash(self.password_hash, password)
|
||||
|
||||
def is_superadmin(self):
|
||||
return self.rolle == 'superadmin'
|
||||
|
||||
def is_firmadmin(self):
|
||||
return self.rolle == 'firmadmin'
|
||||
|
||||
def is_admin(self):
|
||||
return self.rolle in ('firmadmin', 'superadmin')
|
||||
|
||||
def hat_zugriff(self, project, required='lesen'):
|
||||
if self.is_superadmin():
|
||||
return True
|
||||
if self.is_firmadmin():
|
||||
from app.models.project import Project
|
||||
return Project.query.get(project.id).company_id == self.company_id
|
||||
from app.models.project_access import ProjectAccess
|
||||
access = ProjectAccess.query.filter_by(
|
||||
user_id=self.id, project_id=project.id
|
||||
).first()
|
||||
if not access:
|
||||
return False
|
||||
if required == 'lesen':
|
||||
return True
|
||||
if required == 'schreiben':
|
||||
return access.zugriff in ('lesen', 'schreiben')
|
||||
return False
|
||||
|
||||
def __repr__(self):
|
||||
return f'<User {self.email} ({self.rolle})>'
|
||||
@@ -0,0 +1,14 @@
|
||||
from app.extensions import db
|
||||
|
||||
class UserModulePermission(db.Model):
|
||||
__tablename__ = 'user_module_permissions'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
module_id = db.Column(db.Integer, db.ForeignKey('modules.id'), nullable=False)
|
||||
aktiv = db.Column(db.Boolean, default=True)
|
||||
|
||||
user = db.relationship('User', backref='user_module_list')
|
||||
module = db.relationship('Module', backref='user_assignments')
|
||||
|
||||
__table_args__ = (db.UniqueConstraint('user_id', 'module_id'),)
|
||||
@@ -0,0 +1,34 @@
|
||||
from app.extensions import db
|
||||
from datetime import datetime
|
||||
import json
|
||||
|
||||
class ViewProfile(db.Model):
|
||||
__tablename__ = 'view_profiles'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
name = db.Column(db.String(100), nullable=False)
|
||||
view_type = db.Column(db.String(50), default='lv') # lv, aufmass, ...
|
||||
config_json = db.Column(db.Text, default='{}')
|
||||
is_default = db.Column(db.Boolean, default=False)
|
||||
erstellt_am = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
def get_config(self):
|
||||
try:
|
||||
return json.loads(self.config_json or '{}')
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
return {}
|
||||
|
||||
def set_config(self, config):
|
||||
self.config_json = json.dumps(config)
|
||||
|
||||
@staticmethod
|
||||
def get_default_config():
|
||||
return {
|
||||
'column_order': ['fav', 'drag', 'pos_nr', 'text', 'einheit', 'ep', 'aktion'],
|
||||
'column_widths': {'fav': 32, 'drag': 28, 'pos_nr': 90, 'text': 400, 'einheit': 60, 'ep': 80, 'aktion': 70},
|
||||
'column_visible': {'fav': True, 'drag': True, 'pos_nr': True, 'text': True, 'einheit': True, 'ep': True, 'aktion': True},
|
||||
}
|
||||
|
||||
def __repr__(self):
|
||||
return f'<ViewProfile {self.name} ({self.view_type})>'
|
||||
Reference in New Issue
Block a user