Compare commits

..

21 Commits

Author SHA256 Message Date
e81407b43d Merge linuxero 2025-02-27 14:48:08 +01:00
73542e8089 Backup Config 2025-02-27 14:45:27 +01:00
89e96422cc Merge branch 'refs/heads/linuxero' 2025-02-27 14:44:13 +01:00
eacd3dacc7 Merge branch 'main' into linuxero - Objects first step 2025-02-27 14:43:59 +01:00
e0ec99098e Fixing ObjectAddOnContactPerson.qml conflict 2025-02-27 14:28:27 +01:00
6bf6ff3111 Fixing ObjectAddOnContactPerson.qml conflict 2025-02-27 14:20:15 +01:00
4c62834369 merge main 2025-02-27 09:39:40 +01:00
e528729181 BackupSettings 2025-02-27 08:52:33 +01:00
d7928d25fc Objekte anlegen 2025-02-26 16:59:20 +01:00
bd2316dbfb BackupSettings.qml 2025-02-26 15:35:34 +01:00
82b3c2d403 test 2025-02-26 15:24:24 +01:00
8ee303227e Merge linuxero 2025-02-26 15:20:33 +01:00
2a09fed57a Test 2025-02-26 15:15:39 +01:00
e7d0b7cdb5 i dont know what im doing 2025-02-26 15:10:42 +01:00
f0cde5ec20 Fehler 2025-02-26 15:09:28 +01:00
3738bf1c6e Mitarbeiter anlegen funktioniert 2025-02-26 10:33:01 +01:00
dec4ca59f0 Merge linuxero 2025-02-26 09:23:28 +01:00
0f253c518d Configuration menu entry 2025-02-26 09:12:34 +01:00
7228d5fae9 Merge branch 'main' into schnacke
asdasd
2025-02-25 16:24:15 +01:00
e2410d0852 Änderung AddNewObject 2025-02-25 16:23:49 +01:00
cc25f85771 Objekt Formular bearbeitet 2025-02-25 15:58:58 +01:00
21 changed files with 505 additions and 156 deletions

View File

@@ -145,8 +145,21 @@ ColumnLayout
} }
} }
} }
Component.onCompleted:
{
employee_model.addedNewEmployee.connect(onAddNewEmployee)
}
// } // }
// } // ScrollView // } // ScrollView
function onAddNewEmployee(added)
{
if (added)
console.log('addedsuccesfully')
else
console.log('failedtoadd')
appLoader.source = 'EmployeeTable.qml'
}
function checkFields() function checkFields()
{ {

View File

@@ -11,19 +11,6 @@ GridLayout
Layout.fillHeight: true Layout.fillHeight: true
rowSpacing: 9 rowSpacing: 9
Label
{
text: qsTr("Firma")
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
}
ComboBox
{
property string name: "business"
id: business
editable: true
Layout.fillWidth: true
Layout.columnSpan: 3
}
//// New grid row //// New grid row
@@ -121,7 +108,7 @@ GridLayout
SpinBox SpinBox
{ {
property string name: "partitions" property string name: "units"
id: partitions id: partitions
Layout.fillWidth: true Layout.fillWidth: true
from: 1 from: 1
@@ -158,7 +145,7 @@ GridLayout
id: mezzanin id: mezzanin
Layout.fillWidth: true Layout.fillWidth: true
editable: false editable: false
model: [qsTr("Jööö"), qsTr("Nöööööööööööööööööööööööööö")] model: [qsTr("Ja"), qsTr("Nein")]
} }
Label Label
@@ -173,11 +160,24 @@ GridLayout
id: lift id: lift
Layout.fillWidth: true Layout.fillWidth: true
editable: false editable: false
model: [qsTr("Jööö"), qsTr("Nöööööööööööööööööööööööööö")] model: [qsTr("Ja"), qsTr("Nein")]
} }
//New grid row //New grid row
Label
{
text: qsTr("Objekt-Nr.")
Layout.alignment: Qt.AlignRight
}
TextField
{
property string name: "objectno"
id: objectno
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
placeholderText: qsTr("0 oder leer um eine Nummer automatisch zu generieren")
placeholderTextColor: "pink"
}
Label Label
@@ -195,20 +195,7 @@ GridLayout
} }
//// New grid row //// New grid row
Label
{
text: qsTr("Kontaktdaten")
Layout.alignment: Qt.AlignRight | Qt.AlignTop
}
ComboBox
{
property string name: "contact"
id: contact
Layout.fillWidth: true
editable: false
model: [qsTr("Beirat"), qsTr("Hausmeister")]
}
Label Label
{ {
@@ -218,8 +205,8 @@ GridLayout
TextField TextField
{ {
property string name: "cleansing" property string name: "cleaningproducts"
id: cleansing id: cleaningproducts
Layout.fillWidth: true Layout.fillWidth: true
placeholderText: "Pflichtfeld" placeholderText: "Pflichtfeld"
placeholderTextColor: "red" placeholderTextColor: "red"
@@ -232,10 +219,12 @@ GridLayout
function checkObjectField() function checkObjectField()
{ {
return (street.text.trim() && houseno.text.trim() &&
return street.text.trim() && houseno.text.trim() &&
(postcode.editText.trim() || postcode.currentText.trim()) && (postcode.editText.trim() || postcode.currentText.trim()) &&
(city.editText.trim() || city.currentText.trim()) && (city.editText.trim() || city.currentText.trim()) &&
cleansing.text.trim()) cleaningproducts.text.trim()
} }
} }

View File

@@ -71,19 +71,20 @@ ColumnLayout
enabled: false enabled: false
onClicked: onClicked:
{ {
new_object = JsLib.parseForm(newObject)
new_object['lift'] = new_object['lift'] === 'Ja' ? 1 : 0
new_object['mezzanin'] = new_object['mezzanin'] === 'Ja' ? 1 : 0
if (!checkAddContact.checked) if (!checkAddContact.checked)
{ {
var list = [] var list = []
new_object = JsLib.parseForm(newObject) object_model.addObject(new_object, list, false)
object_model.addObject(new_object, list)
} }
else else
{ {
new_object = JsLib.parseForm(newObject)
var new_objecto = addObjectLayout.getForm() var new_objecto = addObjectLayout.getForm()
object_model.addObject(new_object, new_objecto) object_model.addObject(new_object, new_objecto, true)
} }
} }
} }
@@ -94,7 +95,10 @@ ColumnLayout
Layout.fillHeight: true Layout.fillHeight: true
} }
Component.onCompleted:
{
object_model.objectAdded.connect(onObjectAdded)
}
// Connections // Connections
// { // {
@@ -108,6 +112,13 @@ ColumnLayout
// } // }
// } // }
function onObjectAdded(added)
{
if (!added)
console.log(qsTr("Fehler beim Objekt-Anlegen!"))
appLoader.source = "ObjectTable.qml"
}
function checkFields() function checkFields()
{ {
if(checkAddContact.checked) if(checkAddContact.checked)

115
Gui/BackupSettings.qml Normal file
View File

@@ -0,0 +1,115 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import QtCore
import "../js/qmldict.js" as JsLib
GridLayout
{
anchors.fill: parent
anchors.topMargin: 150
columns: 2
Label
{
Layout.columnSpan: 2
Layout.alignment: Qt.AlignHCenter
text: qsTr("Sicherung")
font.pixelSize: 35
}
Label
{
text: qsTr("Konfiguration")
Layout.alignment: Qt.AlignRight
}
Button
{
id: saveConfig
text: qsTr("Jetzt sichern!")
onClicked: dialog.open()
}
Label
{
text: qsTr("Verschlüsselung")
Layout.alignment: Qt.AlignRight
}
Button
{
id: saveEncryption
text: qsTr("Jetzt sichern!")
onClicked: apploader.item.recoverEnc.open()
}
Item
{
id: spacer
Layout.fillHeight: true
}
Dialog
{
anchors.centerIn: parent
id: dialog
title: "Title"
standardButtons: Dialog.Apply | Dialog.Cancel
onApplied:
{
if (configPwd.text === repeatConfigPwd.text)
{
saveConfigFile.open()
}
else
{
configPwd.text = ""
configPwd.placeholderText = qsTr("Passwort stimmt nicht überein")
configPwd.placeholderTextColor = "red"
repeatConfigPwd.placeholderText = qsTr("")
repeatConfigPwd.text = ""
}
}
onRejected: console.log("Cancel clicked")
GridLayout
{
id: gridPw
columns: 2
Label
{
text: qsTr("Passwort eingeben")
}
TextField
{
id: configPwd
placeholderText: qsTr("Sicherungspasswort festlegen")
}
Label
{
text: qsTr("Passwort wiederholen")
}
TextField
{
property string name: "password"
id: repeatConfigPwd
placeholderText: qsTr("Sicherungspasswort wiederholen")
}
}
}
FileDialog
{
id: saveConfigFile
fileMode: FileDialog.SaveFile
nameFilters: ["PYQCRM Recovery files (*.pyqrec)"]
currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
onAccepted:
{
var pw = JsLib.parseForm(gridPw)
config.backupConfig(saveConfigFile.currentFile, pw["password"])
}
}
}

17
Gui/CompanyConf.qml Normal file
View File

@@ -0,0 +1,17 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
Item
{
property string name: "company"
anchors.fill: parent
Label
{
text: qsTr("Das Unternehmen")
anchors.centerIn: parent
font.pixelSize: 57
font.bold: true
}
}

View File

@@ -11,7 +11,9 @@ Item
{ {
property string recpass: "" property string recpass: ""
property bool adminAvailable: true property bool adminAvailable: true
property alias recoverEnc: recoveryPaswordDialog
id: firstStartItem
anchors.fill: parent anchors.fill: parent
StackView StackView
{ {
@@ -87,6 +89,7 @@ Item
Dialog Dialog
{ {
id: recoveryPaswordDialog id: recoveryPaswordDialog
modal: true modal: true
title: qsTr("Wiederherstellung") title: qsTr("Wiederherstellung")
@@ -115,6 +118,19 @@ Item
implicitWidth: 300 implicitWidth: 300
placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben") placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben")
} }
Label
{
text: qsTr("Wiederherstellungspasswort eingeben: ")
}
TextField
{
id: repeatRecoveryPaswordInput
text: ""
echoMode: TextInput.Password
implicitWidth: 300
placeholderText: qsTr("Hier Wiederherstellungspasswort eingeben")
}
} }
} }
} }

View File

@@ -7,6 +7,21 @@ GridLayout
property var contacts: null property var contacts: null
columns: 2 columns: 2
Label
{
text: qsTr("Kontaktdaten")
Layout.alignment: Qt.AlignRight | Qt.AlignTop
}
ComboBox
{
property string name: "contacttype"
id: contacttype
Layout.fillWidth: true
editable: false
model: [qsTr("Beirat"), qsTr("Hausmeister")]
}
Label Label
{ {
text: qsTr("Anrede") text: qsTr("Anrede")
@@ -114,6 +129,7 @@ GridLayout
if (Object.keys(contacts).length === 0) if (Object.keys(contacts).length === 0)
{ {
enabled = false enabled = false
console.log(contacts)
} }
checkFields() checkFields()
} }
@@ -124,7 +140,7 @@ GridLayout
{ {
id: addContact id: addContact
text: qsTr("Hinzufügen") text: qsTr("Hinzufügen")
enabled: firstname.text.trim() && lastname.text.trim() && (phonenumber.text.trim() || mobile.text.trim()) && posizion.text.trim() enabled: firstname.text.trim() && lastname.text.trim() && (phonenumber.text.trim() || mobile.text.trim()) && posizion.text.trim() && (contacts === null || Object.keys(contacts).length < 3)
onClicked: onClicked:
{ {
var num_contacts = 0 var num_contacts = 0
@@ -150,11 +166,6 @@ GridLayout
mobile.text = "" mobile.text = ""
posizion.text = "" posizion.text = ""
if (Object.keys(contacts).length >= 3)
{
enabled = false
}
removeContact.enabled = true removeContact.enabled = true
checkFields() checkFields()
} }
@@ -220,6 +231,25 @@ GridLayout
} }
} }
Component
{
id: highlight
Rectangle
{
width: 230; height: 15
color: "lightsteelblue"; radius: 5
y: contactView.currentItem.y
Behavior on y
{
SpringAnimation
{
spring: 3
damping: 0.2
}
}
}
}
Rectangle Rectangle
{ {
id: mainRect id: mainRect
@@ -237,11 +267,12 @@ GridLayout
header: headline header: headline
highlight: Rectangle { color: "grey"} highlight: Rectangle { color: "grey"}
highlightFollowsCurrentItem: false highlightFollowsCurrentItem: false
onActiveFocusChanged: if(!focus) currentIndex = -1 onActiveFocusChanged: if(!focus) currentIndex = -1
delegate: Item delegate: Item
{ {
width: contactView.width width: contactView.width
height: 15 height: 15
MouseArea MouseArea
{ {
@@ -253,6 +284,7 @@ GridLayout
} }
} }
Row Row
{ {
//spacing: 9 //spacing: 9
@@ -286,6 +318,8 @@ GridLayout
} }
} }
} }
} }
} }
} }

View File

@@ -15,13 +15,13 @@ Item
Button Button
{ {
text: qsTr("Objekts zeigen") text: qsTr("Zurück zu den Objekten")
onClicked: customersStack.pop() onClicked: objectsStack.pop()
} }
} }
Component.onCompleted: Component.onCompleted:
{ {
business_model.onRowClicked(selectedObject) object_model.onRowClicked(selectedObject)
} }
} }

View File

@@ -39,7 +39,7 @@ Item
id: horizontalHeaderview id: horizontalHeaderview
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: 40 implicitHeight: 40
visible: false //visible: false
movableColumns: true //@disable-check M16 movableColumns: true //@disable-check M16
syncView: objectTable syncView: objectTable
@@ -68,36 +68,22 @@ Item
id: objectTable id: objectTable
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
columnSpacing: 1
rowSpacing: 2
model: object_model
alternatingRows: true
resizableColumns: true // @disable-check M16
selectionBehavior: TableView.SelectRows
ScrollBar.vertical: ScrollBar ScrollBar.vertical: ScrollBar
{ {
policy: objectTable.contentHeight > objectTable.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff policy: objectTable.contentHeight > objectTable.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
} }
columnSpacing: 1
rowSpacing: 2
//model: object_model
alternatingRows: true
resizableColumns: true // @disable-check M16
selectionBehavior: TableView.SelectRows
selectionModel: ItemSelectionModel selectionModel: ItemSelectionModel
{ {
id: obmodel id: obmodel
model: objectTable.model model: objectTable.model
} }
// Timer
// {
// id: redrawTable
// running: true
// interval: 1
// repeat: false
// onTriggered:
// {
// objectTable.forceLayout();
// }
// }
delegate:Rectangle delegate:Rectangle
{ {
required property bool selected required property bool selected
@@ -112,7 +98,7 @@ Item
Text Text
{ {
text: model.display === null? "": model.display text: (model.display === null || model.display === undefined)? "": model.display
elide: Text.ElideRight elide: Text.ElideRight
width: parent.width width: parent.width
height: parent.height height: parent.height

112
Gui/PyqcrmConf.qml Normal file
View File

@@ -0,0 +1,112 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
Item
{
anchors.fill: parent
TabBar
{
id: bar
width: parent.width
TabButton
{
text: qsTr("Benutzer")
}
TabButton
{
text: qsTr("Datenbank")
}
TabButton
{
text: qsTr("Das Unternehmen")
}
TabButton
{
text: qsTr("Sicherung")
}
}
StackLayout
{
id: confContainer
anchors.fill: parent
currentIndex: bar.currentIndex
Item
{
id: userTab
UsersPage
{
id: usersPage
anchors.fill: parent
}
}
Item
{
id: dbTab
DbConfiguration
{
id: dbConf
anchors.fill: parent
}
}
Item
{
id: companyTab
CompanyConf
{
id: companyConf
anchors.fill: parent
}
}
Item
{
id: backup
BackupSettings
{
id: backupSettings
anchors.fill: parent
}
}
}
RowLayout
{
width: parent.width
anchors.bottom: parent.bottom
Item
{
Layout.fillWidth: true
}
Button
{
text: qsTr("Ablehnen")
onClicked: appLoader.source = "Dashboard.qml"
}
Button
{
text: qsTr("Speichern")
onClicked:
{
switch (confContainer.currentIndex)
{
case 1:
console.log("Need to update DB paramenters")
break
case 2:
console.log("Need to update company's info.")
break
default:
console.log("Need to handle users")
}
}
}
}
}

View File

@@ -178,8 +178,15 @@ RowLayout
id: mainMenu id: mainMenu
MenuItem MenuItem
{ {
text: qsTr("Benutzer-Verwaltung") //text: qsTr("Benutzer-Verwaltung")
onTriggered: appLoader.source = "UsersPage.qml" //onTriggered: appLoader.source = "UsersPage.qml"
text: qsTr("Einstellungen")
onTriggered:
{
// TODO: Check if logged-in user is admin first!!
appLoader.source = "PyqcrmConf.qml"
}
} }
MenuSeparator {} MenuSeparator {}
MenuItem { text: qsTr("Als PDF exportieren") } MenuItem { text: qsTr("Als PDF exportieren") }

View File

@@ -4,6 +4,7 @@ import QtQuick.Controls
Item Item
{ {
property string name: "users"
anchors.fill: parent anchors.fill: parent
Label Label

View File

@@ -12,6 +12,8 @@ ApplicationWindow
visible: true visible: true
title: "PYQCRM" title: "PYQCRM"
property string confile: "" property string confile: ""
property alias settingsFileDialog: settingsFiledialog
TopBar TopBar
{ {
@@ -80,17 +82,18 @@ ApplicationWindow
anchors.centerIn: parent anchors.centerIn: parent
standardButtons: Dialog.Yes | Dialog.No standardButtons: Dialog.Yes | Dialog.No
onAccepted: settingsFiledialog.open() onAccepted: settingsFiledialog.open()
onRejected: appLoader.source= "firststart.qml" onRejected: appLoader.source= "Firststart.qml"
title: qsTr("Einstellungen importieren") title: qsTr("Einstellungen importieren")
} }
FileDialog FileDialog
{ {
id: settingsFiledialog id: settingsFiledialog
title: qsTr("PYQCRM Einstellungen") title: qsTr("PYQCRM Einstellungen")
currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0] currentFolder: StandardPaths.standardLocations(StandardPaths.DocumentsLocation)[0]
modality: "ApplicationModal" modality: "ApplicationModal"
nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqcrm)")] nameFilters: [qsTr("PYQCRM Einstellungen (*.pyqrec)")]
onAccepted: onAccepted:
{ {
exportFilePassword.open() exportFilePassword.open()

1
enc_key_backup.txt Normal file
View File

@@ -0,0 +1 @@
Lj30yFOP7hJmY5Cub1Go8fJz0UE+Zyo9cEqNxfY23Sc=

View File

@@ -110,6 +110,12 @@ class ConfigLoader(QObject):
self.backupEncryptionKey.emit() self.backupEncryptionKey.emit()
return admin return admin
"""###################################################"""
""" """
""" TODO: Rename method and rename self.__encrypt_key """
""" """
"""###################################################"""
@Slot(str, str) @Slot(str, str)
def saveRecoveryKey(self, recovery_file, recovery_password): def saveRecoveryKey(self, recovery_file, recovery_password):
# print(f"In {__file__} file, saveRecoveryKey()") # print(f"In {__file__} file, saveRecoveryKey()")
@@ -131,30 +137,39 @@ class ConfigLoader(QObject):
@Slot(str, str) @Slot(str, str)
def getRecoveryKey(self, recovery_file, recovery_password): def getRecoveryKey(self, recovery_file, recovery_password):
# print(f"In {__file__} file, getRecoveryKey()")
local = False
rec_file = urlparse(recovery_file) rec_file = urlparse(recovery_file)
rec_file = rec_file.path rec_file = rec_file.path
if os.name == "nt": if os.name == "nt":
rec_file = rec_file [1:] rec_file = rec_file [1:]
try: try:
with open(rec_file, "r") as f: ek = self.__parseImport(rec_file, recovery_password)
rf = f.read()
rf = Vermasseln().entschluesseln(rf, local) if ek:
ek = rf[128:] self.__setEncryptionKey(ek)
ek = ek[:-32] self.configurationReady.emit()
password = rf[:128] else:
salt = rf[-32:] self.__invalidateEncryptionKey()
ok = self.__checkRecoveryPassword(recovery_password, password, salt) self.invalidEncryptionKey.emit()
if ok:
self.__setEncryptionKey(ek)
self.configurationReady.emit()
else:
self.__invalidateEncryptionKey()
self.invalidEncryptionKey.emit()
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
def __parseImport(self, rec_file, recovery_password):
local = False
with open(rec_file, "r") as f:
rf = f.read()
rf = Vermasseln().entschluesseln(rf, local)
ek = rf[128:]
ek = ek[:-32]
password = rf[:128]
salt = rf[-32:]
ok = self.__checkRecoveryPassword(recovery_password, password, salt)
if ok:
return ek
else:
return None
def __invalidateEncryptionKey(self): def __invalidateEncryptionKey(self):
# print(f"In {__file__} file, __invalidateEncryptionKey()") # print(f"In {__file__} file, __invalidateEncryptionKey()")
self.__config['pyqcrm']['ENCRYPTION_KEY_VALID'] = 'No' self.__config['pyqcrm']['ENCRYPTION_KEY_VALID'] = 'No'
@@ -173,13 +188,25 @@ class ConfigLoader(QObject):
@Slot(str, str) # todo: non local encryption @Slot(str, str) # todo: non local encryption
def importConfig(self, confile, password): def importConfig(self, confile, password):
# print(f"In {__file__} file, importConfig()")
confile = urlparse(confile) confile = urlparse(confile)
confile = confile.path confile = confile.path
if os.name == "nt": if os.name == "nt":
confile = confile[1:] confile = confile[1:]
shutil.copyfile(confile, self.config_dir+ '/pyqcrm.toml') try:
ek = self.__parseImport(confile, password)
if ek:
self.__config = toml.loads(ek)
self.__saveConfig()
self.configurationReady.emit()
else:
self.invalidEncryptionKey.emit()
except Exception as e:
print(str(e))
def __configLoad(self): def __configLoad(self):
# print(f"In {__file__} file, __configLoad()") # print(f"In {__file__} file, __configLoad()")
@@ -195,6 +222,7 @@ class ConfigLoader(QObject):
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
def getConfig(self): def getConfig(self):
# print(f"In {__file__} file, getConfig()") # print(f"In {__file__} file, getConfig()")
# print(self.__config) # print(self.__config)
@@ -212,3 +240,8 @@ class ConfigLoader(QObject):
self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key self.__config['pyqcrm']['ENCRYPTION_KEY'] = enc_key
self.__saveConfig() self.__saveConfig()
@Slot(str, str)
def backupConfig(self, filename, password):
self.__encrypt_key = toml.dumps(self.getConfig())
self.saveRecoveryKey(filename, password)

View File

@@ -6,7 +6,7 @@ from ..PyqcrmFlags import PyqcrmAppliEmpyFlags
class EmployeeDAO(QObject): class EmployeeDAO(QObject):
newEmployeeAdded = Signal() newEmployeeAdded = Signal(bool)
__cur = None __cur = None
__all_cols = None __all_cols = None
@@ -44,7 +44,8 @@ class EmployeeDAO(QObject):
if self.__cur: if self.__cur:
self.__cur.callproc("addApplicant", (json.dumps(data), applicant, enc_key,)) self.__cur.callproc("addApplicant", (json.dumps(data), applicant, enc_key,))
self.__con.commit() self.__con.commit()
self.newEmployeeAdded.emit() self.newEmployeeAdded.emit(True)
except mariadb.Error as e: except mariadb.Error as e:
print(str(e)) print(str(e))
self.newEmployeeAdded.emit(False)

View File

@@ -6,6 +6,7 @@ import re
class EmployeeModel(QAbstractTableModel): class EmployeeModel(QAbstractTableModel):
addedNewEmployee = Signal(bool)
__data = None __data = None
__employee_dao = None __employee_dao = None
__visible_index = None __visible_index = None
@@ -26,17 +27,20 @@ class EmployeeModel(QAbstractTableModel):
@Slot(dict, bool) @Slot(dict, bool)
def addEmployee(self, new_employee, applicant = True): def addEmployee(self, new_employee, applicant = True):
new_employee['worklicense'] = int(new_employee['worklicense']) if 'worklicense' in new_employee:
new_employee['residencetype'] = int(new_employee['residencetype']) new_employee['worklicense'] = int(new_employee['worklicense'])
new_employee['residencetype'] = int(new_employee['residencetype'])
self.__employee_dao.addEmployee(new_employee, self.__key, applicant) self.__employee_dao.addEmployee(new_employee, self.__key, applicant)
@Slot(str) @Slot(str)
def viewCriterion(self, criterion, processed = False, fired = False): def viewCriterion(self, criterion, processed = False, fired = False):
self.__getData(criterion, processed, fired) self.__getData(criterion, processed, fired)
@Slot() @Slot(bool)
def __refreshView(self): def __refreshView(self, added):
self.__getData() if added:
self.__getData()
self.addedNewEmployee.emit(added)
def __getData(self, criterion = "Alle", processed = False, fired = False, every_state = True): def __getData(self, criterion = "Alle", processed = False, fired = False, every_state = True):
self.beginResetModel() self.beginResetModel()

View File

@@ -6,7 +6,7 @@ from ..PyqcrmFlags import PyqcrmAppliEmpyFlags
class ObjectDAO(QObject): class ObjectDAO(QObject):
newObjectAdded = Signal() newObjectAdded = Signal(bool)
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@@ -20,7 +20,18 @@ class ObjectDAO(QObject):
if self.__cur: if self.__cur:
self.__cur.callproc("addObject", (json.dumps(new_object), json.dumps(new_objcontact), enc_key,)) self.__cur.callproc("addObject", (json.dumps(new_object), json.dumps(new_objcontact), enc_key,))
self.__con.commit() self.__con.commit()
# self.newEmployeeAdded.emit() self.newObjectAdded.emit(True)
except mariadb.Error as e:
self.newObjectAdded.emit(False)
print(str(e))
def getObjects(self, criterion, enc_key = None):
try:
if self.__cur:
self.__cur.callproc("getObjects", (criterion, enc_key,))
self.__all_cols = [desc[0] for desc in self.__cur.description]
return self.__cur.fetchall(), self.__all_cols
else:
return None, None
except mariadb.Error as e: except mariadb.Error as e:
print(str(e)) print(str(e))

View File

@@ -6,6 +6,8 @@ import re
import json import json
class ObjectModel(QAbstractTableModel): class ObjectModel(QAbstractTableModel):
objectAdded = Signal(bool)
__data = None __data = None
__object_dao = None __object_dao = None
__visible_index = None __visible_index = None
@@ -22,15 +24,15 @@ class ObjectModel(QAbstractTableModel):
self.__object_dao.newObjectAdded.connect(self.__refreshView) self.__object_dao.newObjectAdded.connect(self.__refreshView)
self.__conf = ConfigLoader().getConfig() self.__conf = ConfigLoader().getConfig()
self.__key = self.__conf['pyqcrm']['ENCRYPTION_KEY'] self.__key = self.__conf['pyqcrm']['ENCRYPTION_KEY']
#self.__getData() self.__object_dao.newObjectAdded.connect(self.objectAdded)
self.__getData()
@Slot(dict, list, bool) @Slot(dict, list, bool)
def addObject(self, new_object, new_objcontact): def addObject(self, new_object, new_objcontact = None, new_contact = False):
print(new_object) #print(new_object)
print(new_objcontact) print(new_objcontact)
self.__object_dao.addObject(new_object, new_objcontact, self.__key) self.__object_dao.addObject(new_object, new_objcontact, self.__key)
# @Slot(str) # @Slot(str)
@@ -41,54 +43,45 @@ class ObjectModel(QAbstractTableModel):
def __refreshView(self): def __refreshView(self):
self.__getData() self.__getData()
# def __getData(self, criterion = "Alle", processed = False, fired = False, every_state = True): def __getData(self, criterion = "Alle"):
# self.beginResetModel() self.beginResetModel()
# rows, self.__visible_columns = self.__employee_dao.getEmployees(self.__key, criterion, processed, fired, every_state) rows, self.__visible_columns = self.__object_dao.getObjects(criterion, self.__key)
# self.__data = rows self.__data = rows
# self.endResetModel() self.endResetModel()
# def rowCount(self, parent= QModelIndex()): def rowCount(self, parent= QModelIndex()):
# return len (self.__data) return len (self.__data)
# def columnCount(self, parent= QModelIndex()): def columnCount(self, parent= QModelIndex()):
# return len(self.__visible_columns) - self.__col_skip return len(self.__visible_columns) - self.__col_skip
# @Slot(str, bool, bool, bool) @Slot(str)
# def viewCriterion(self, criterion, processed, fired, every_state): def viewCriterion(self, criterion):
# self.__everyone = True if criterion == 'Alle' else False self.__getData(criterion)
# if self.__everyone and criterion != "Alle":
# self.__col_skip = 2
# else:
# self.__col_skip = 2
# self.__getData(criterion, processed, fired, every_state)
# def data(self, index, role= Qt.DisplayRole): def data(self, index, role= Qt.DisplayRole):
# if role == Qt.DisplayRole: if role == Qt.DisplayRole:
# row = self.__data[index.row()] row = self.__data[index.row()]
# applicant_col = index.column() + self.__col_skip applicant_col = index.column() + self.__col_skip
# tr = row[applicant_col] #if type(row[index.column() + 2]) is str else str(row[index.column() + 2], "utf-8") tr = row[applicant_col] #if type(row[index.column() + 2]) is str else str(row[index.column() + 2], "utf-8")
# if applicant_col == 2 and self.__everyone: #print(f"Data: {tr}")
# tr = 'Ja' if tr == 1 else 'Nein' # return row[index.column() + 2]
# else: return tr
# tr = re.sub("Keine Angabe ","", tr) return None
# #print(f"Data: {tr}")
# # return row[index.column() + 2]
# return tr
# return None
# def headerData(self, section, orientation, role = Qt.DisplayRole): def headerData(self, section, orientation, role = Qt.DisplayRole):
# if orientation == Qt.Horizontal and role == Qt.DisplayRole: if orientation == Qt.Horizontal and role == Qt.DisplayRole:
# self.__col_name = self.__visible_columns[section + self.__col_skip] self.__col_name = self.__visible_columns[section + self.__col_skip]
# return self.__col_name return self.__col_name
# return super().headerData(section, orientation, role) return super().headerData(section, orientation, role)
# @Slot(int) @Slot(int)
# def onRowClicked(self, row): def onRowClicked(self, row):
# #print(self.__data) #print(self.__data)
# print(f"Selected table row: {row}, corresponding DB ID: {self.__data[row][0]}") print(f"Selected table row: {row}, corresponding DB ID: {self.__data[row][0]}")
# #if not self.__employee_dict['employee'] or self.__data[row][0] != self.__employee_dict['employee']['id']: #if not self.__employee_dict['employee'] or self.__data[row][0] != self.__employee_dict['employee']['id']:
# #self.__employee = self.__employee_dao.getEmployee(self.__data[row][0], self.__key) #self.__employee = self.__employee_dao.getEmployee(self.__data[row][0], self.__key)
# #print(self.__business) #print(self.__business)
# #self.__getEmployeeInfo() #self.__getEmployeeInfo()
# # self.__getContactInfo() # self.__getContactInfo()
# # print(self.__business_dict) # print(self.__business_dict)

View File

@@ -20,7 +20,7 @@ class Vermasseln:
return storable_data return storable_data
def entschluesseln(self, data, local= True): def entschluesseln(self, data, local = True):
try: try:
data_list = data.split(".") data_list = data.split(".")
encoded_data = [b64decode(x) for x in data_list] encoded_data = [b64decode(x) for x in data_list]
@@ -37,7 +37,7 @@ class Vermasseln:
return decrypted_data return decrypted_data
def __vermasslungsKobold(self, local= True): def __vermasslungsKobold(self, local = True):
key = platform.processor().encode("utf-8") if local else b"(==daniishtverhaftetwegensexy#)" key = platform.processor().encode("utf-8") if local else b"(==daniishtverhaftetwegensexy#)"
key = key[0:31] key = key[0:31]
hash_key = SHA256.new(key) hash_key = SHA256.new(key)
@@ -53,7 +53,6 @@ class Vermasseln:
hash_pw = (salt + password).encode("utf-8") hash_pw = (salt + password).encode("utf-8")
h_obj = SHA3_512.new(hash_pw) h_obj = SHA3_512.new(hash_pw)
password = salt + "$" + h_obj.hexdigest() password = salt + "$" + h_obj.hexdigest()
return password return password

View File

@@ -10,7 +10,6 @@
<file>Gui/CustomerTable.qml</file> <file>Gui/CustomerTable.qml</file>
<file>Gui/Dashboard.qml</file> <file>Gui/Dashboard.qml</file>
<file>Gui/EmployeeTable.qml</file> <file>Gui/EmployeeTable.qml</file>
<file>Gui/firststart.qml</file>
<file>Gui/main.qml</file> <file>Gui/main.qml</file>
<file>Gui/SearchBar.qml</file> <file>Gui/SearchBar.qml</file>
<file>js/qmldict.js</file> <file>js/qmldict.js</file>
@@ -42,5 +41,9 @@
<file>Gui/CustomerDetailsView.qml</file> <file>Gui/CustomerDetailsView.qml</file>
<file>Gui/ReadMe.qml</file> <file>Gui/ReadMe.qml</file>
<file>Gui/UsersPage.qml</file> <file>Gui/UsersPage.qml</file>
<file>Gui/PyqcrmConf.qml</file>
<file>Gui/CompanyConf.qml</file>
<file>Gui/Firststart.qml</file>
<file>Gui/BackupSettings.qml</file>
</qresource> </qresource>
</RCC> </RCC>