diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..9540b3e
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ mariadb
+ true
+ org.mariadb.jdbc.Driver
+ jdbc:mariadb://bearybot.selfhost.co:8080/pyqcrm
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 104102c..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 449e696..0000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Gui/Employees/AddApplicant.qml b/Gui/Employees/AddApplicant.qml
index 630fa6b..ed967fe 100644
--- a/Gui/Employees/AddApplicant.qml
+++ b/Gui/Employees/AddApplicant.qml
@@ -6,13 +6,6 @@ ColumnLayout {
anchors.fill: parent
spacing: Dimensions.l
- Component.onCompleted: {
- employee_model.addedNewEmployee.connect(successful => {
- if (successful)
- contentStack.pop();
- });
- }
-
ApplicantForm {
id: applicantForm
@@ -36,7 +29,8 @@ ColumnLayout {
text: qsTr("Speichern")
onClicked: {
- employee_model.addApplicant(applicantForm.value);
+ applicantModel.createApplicant(applicantForm.value);
+ contentStack.pop();
}
}
}
diff --git a/Gui/Employees/AddEmployee.qml b/Gui/Employees/AddEmployee.qml
index f05c3b7..1c2a220 100644
--- a/Gui/Employees/AddEmployee.qml
+++ b/Gui/Employees/AddEmployee.qml
@@ -46,7 +46,7 @@ ColumnLayout {
Layout.fillWidth: true
Layout.horizontalStretchFactor: 1
- ApplicantPersonalData {
+ EmployeePersonalData {
id: personalData
implicitWidth: parent.width
@@ -61,14 +61,14 @@ ColumnLayout {
Layout.alignment: Qt.AlignTop
implicitWidth: parent.width
- ApplicantBankData {
+ EmployeeBankData {
id: bankAccount
}
- ApplicantNationalInsurance {
+ EmployeeNationalInsurance {
id: nationalInsurance
}
- ApplicantVarious {
+ EmployeeVarious {
id: applicantVarious
}
diff --git a/Gui/Employees/ApplicantForm.qml b/Gui/Employees/ApplicantForm.qml
index 257dead..66bdd7d 100644
--- a/Gui/Employees/ApplicantForm.qml
+++ b/Gui/Employees/ApplicantForm.qml
@@ -6,19 +6,31 @@ import TeroStyle
ColumnLayout {
readonly property int fieldM: 235
readonly property int fieldS: 110
- readonly property bool valid: city.acceptableInput && email.acceptableInput && firstname.acceptableInput && lastname.acceptableInput && mobile.acceptableInput && phone.acceptableInput && postcode.acceptableInput && formofaddress.acceptableInput && title.acceptableInput
+ readonly property bool valid: emailAddress.acceptableInput && firstName.acceptableInput && houseNumber.acceptableInput && lastName.acceptableInput && mobileNumber.acceptableInput && phoneNumber.acceptableInput && salutation.acceptableInput&& street.acceptableInput && title.acceptableInput && zipCode.acceptableInput
readonly property var value: QtObject {
- readonly property string city: (city.editText ? city.editText : city.currentText) ?? ""
- readonly property string email: email.text
- readonly property string firstname: firstname.text
- readonly property string formofaddress: formofaddress.currentText ?? ""
- readonly property string houseno: houseno.text ?? ""
- readonly property string lastname: lastname.text
- readonly property string mobile: mobile.text
- readonly property string phone: phone.text
- readonly property string postcode: (postcode.editText ? postcode.editText : postcode.currentText) ?? ""
- readonly property string street: (street.editText ? street.editText : street.currentText) ?? ""
+ readonly property string emailAddress: emailAddress.text ?? ""
+ readonly property string firstName: firstName.text ?? ""
+ readonly property string houseNumber: houseNumber.text ?? ""
+ readonly property string lastName: lastName.text ?? ""
+ readonly property string mobileNumber: mobileNumber.text ?? ""
+ readonly property string phoneNumber: phoneNumber.text ?? ""
+ readonly property string salutation: salutation.text ?? ""
+ readonly property string street: street.text ?? ""
readonly property string title: title.currentText
+ readonly property int zipCode: zipCode.currentIndex
+ }
+
+ function setValue(value) {
+ title.currentIndex = value.title ?? 0;
+ firstName.text = value.firstName ?? "";
+ lastName.text = value.lastName ?? "";
+ street.text = value.street ?? "";
+ houseNumber.text = value.houseNumber ?? "";
+ zipCode.currentIndex = value.zipCode ?? -1;
+ phoneNumber.text = value.phoneNumber ?? "";
+ mobileNumber.text = value.mobileNumber ?? "";
+ emailAddress.text = value.emailAddress ?? "";
+ salutation.text = value.salutation ?? 0;
}
spacing: Dimensions.l
@@ -48,13 +60,13 @@ ColumnLayout {
onCurrentTextChanged: {
switch (title.currentIndex) {
case 1:
- formofaddress.text = "Sehr geehrter Herr ";
+ salutation.text = "Sehr geehrter Herr ";
break;
case 2:
- formofaddress.text = "Sehr geehrte Frau ";
+ salutation.text = "Sehr geehrte Frau ";
break;
default:
- formofaddress.text = "Guten Tag ";
+ salutation.text = "Guten Tag ";
}
}
}
@@ -64,7 +76,7 @@ ColumnLayout {
mandatory: true
TextField {
- id: firstname
+ id: firstName
implicitWidth: fieldM
placeholderText: qsTr("Max")
@@ -78,7 +90,7 @@ ColumnLayout {
mandatory: true
TextField {
- id: lastname
+ id: lastName
implicitWidth: fieldM
placeholderText: qsTr("Mustermann")
@@ -92,39 +104,30 @@ ColumnLayout {
spacing: Dimensions.m
Field {
- id: street
-
label: qsTr("Straße")
- mandatory: true
TextField {
+ id: street
+
implicitWidth: fieldM
placeholderText: qsTr("Musterstraße")
-
- validator: NotEmptyValidator {
- }
}
}
Field {
- id: houseno
- mandatory: true
-
label: qsTr("Hausnummer")
TextField {
+ id: houseNumber
+
implicitWidth: fieldS
placeholderText: qsTr("1a")
-
- validator: NotEmptyValidator {
- }
}
}
Field {
label: qsTr("PLZ")
- mandatory: true
ComboBox {
- id: postcode
+ id: zipCode
currentIndex: -1
editable: true
@@ -133,14 +136,11 @@ ColumnLayout {
textRole: "display"
onActivated: currentValue
- onCurrentIndexChanged: city.currentIndex = postcode.currentIndex
-
- validator: NotEmptyValidator {}
+ onCurrentIndexChanged: city.currentIndex = zipCode.currentIndex
}
}
Field {
label: qsTr("Ort")
- mandatory: true
ComboBox {
id: city
@@ -150,9 +150,6 @@ ColumnLayout {
implicitWidth: fieldM
model: address_model
textRole: "city"
-
- validator: NotEmptyValidator {
- }
}
}
}
@@ -173,7 +170,7 @@ ColumnLayout {
label: qsTr("Telefonnummer")
TextField {
- id: phone
+ id: phoneNumber
implicitWidth: fieldM
placeholderText: "+49 1234 567890"
@@ -186,7 +183,7 @@ ColumnLayout {
label: qsTr("Mobil")
TextField {
- id: mobile
+ id: mobileNumber
implicitWidth: fieldM
placeholderText: "+49 123 4567891011"
@@ -199,7 +196,7 @@ ColumnLayout {
label: qsTr("E-Mail Adresse")
TextField {
- id: email
+ id: emailAddress
implicitWidth: fieldM
placeholderText: "tero@example.org"
@@ -212,7 +209,7 @@ ColumnLayout {
label: qsTr("Briefanrede")
TextField {
- id: formofaddress
+ id: salutation
implicitWidth: fieldM
}
diff --git a/Gui/Employees/ApplicantBankData.qml b/Gui/Employees/EmployeeBankData.qml
similarity index 100%
rename from Gui/Employees/ApplicantBankData.qml
rename to Gui/Employees/EmployeeBankData.qml
diff --git a/Gui/Employees/EmployeeDetails.qml b/Gui/Employees/EmployeeDetails.qml
index 8e340aa..8675011 100644
--- a/Gui/Employees/EmployeeDetails.qml
+++ b/Gui/Employees/EmployeeDetails.qml
@@ -1,26 +1,34 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
+import TeroStyle
-Item {
- property var employee
- property int row
+ColumnLayout {
+ property int row: -1
+
+ anchors.fill: parent
+ spacing: Dimensions.l
onRowChanged: {
- employee = employee_model.fetchApplicant(row);
+ if (row !== -1) {
+ applicantForm.setValue(applicantModel.applicant(row))
+ }
}
- ColumnLayout {
- Label {
- text: qsTr("Ausgewählter Mitarbeiter ") + row
- }
- Label {
- text: employee.postcode ?? ""
- }
- Button {
- text: qsTr("Mitarbeiter zeigen")
+ ApplicantForm {
+ id: applicantForm
- onClicked: contentStack.pop()
+ Layout.alignment: Qt.AlignTop
+ Layout.fillHeight: true
+ Layout.verticalStretchFactor: 1
+ }
+
+ RowLayout {
+ spacing: Dimensions.l
+
+ Button {
+ text: qsTr("Als Mitarbeiter:in Einstellen")
+ icon.source: "qrc:/images/InboxArrowDown.svg"
}
}
}
diff --git a/Gui/Employees/ApplicantNationalInsurance.qml b/Gui/Employees/EmployeeNationalInsurance.qml
similarity index 100%
rename from Gui/Employees/ApplicantNationalInsurance.qml
rename to Gui/Employees/EmployeeNationalInsurance.qml
diff --git a/Gui/Employees/ApplicantPersonalData.qml b/Gui/Employees/EmployeePersonalData.qml
similarity index 100%
rename from Gui/Employees/ApplicantPersonalData.qml
rename to Gui/Employees/EmployeePersonalData.qml
diff --git a/Gui/Employees/ApplicantVarious.qml b/Gui/Employees/EmployeeVarious.qml
similarity index 100%
rename from Gui/Employees/ApplicantVarious.qml
rename to Gui/Employees/EmployeeVarious.qml
diff --git a/Gui/Employees/EmployeesTable.qml b/Gui/Employees/EmployeesTable.qml
index ccdd8ed..dc1236d 100644
--- a/Gui/Employees/EmployeesTable.qml
+++ b/Gui/Employees/EmployeesTable.qml
@@ -92,7 +92,7 @@ ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
columnSpacing: 2
- model: employee_model
+ model: applicantModel
resizableColumns: true
rowSpacing: 2
selectionBehavior: TableView.SelectRows
diff --git a/images/InboxArrowDown.svg b/images/InboxArrowDown.svg
new file mode 100644
index 0000000..e62eafc
--- /dev/null
+++ b/images/InboxArrowDown.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/lib/ConfigLoader.py b/lib/ConfigLoader.py
index 3413470..8809bc1 100644
--- a/lib/ConfigLoader.py
+++ b/lib/ConfigLoader.py
@@ -1,19 +1,18 @@
# This Python file uses the following encoding: utf-8
-import toml
-from platformdirs import user_config_dir
-from pathlib import Path
-from PySide6.QtCore import QObject, Slot, Signal
-from .Vermasseln import Vermasseln
-import shutil
-from urllib.parse import urlparse
-from .DB.DbManager import DbManager
import os
-from Crypto.Random import get_random_bytes
from base64 import b64encode
+from pathlib import Path
+from urllib.parse import urlparse
+
+import toml
+from Crypto.Random import get_random_bytes
+from PySide6.QtCore import QObject, Slot, Signal
+from platformdirs import user_config_dir
+
from .DB.UserManager import UserManager
from .PyqcrmFlags import PyqcrmFlags
-
-
+from .Vermasseln import Vermasseln
+from .domain.BaseModel import database
class ConfigLoader(QObject):
@@ -21,7 +20,6 @@ class ConfigLoader(QObject):
__version = "0.1-alpha"
__check_enc_key = True
-
dbConnectionError = Signal(str, bool)
adminUserError = Signal(str, bool)
adminNotAsvailable = Signal()
@@ -31,7 +29,6 @@ class ConfigLoader(QObject):
def __init__(self):
super().__init__()
- # print(f"In {__file__} file, __init__()")
self.config_dir = user_config_dir() + '/pyqcrm'
config_dir = Path(self.config_dir)
if config_dir.exists():
@@ -41,15 +38,13 @@ class ConfigLoader(QObject):
else:
config_dir.mkdir(0o750, True, True)
-
- @Slot(dict, result = bool)
+ @Slot(dict, result=bool)
def setConfig(self, app_config):
- # print(f"In {__file__} file, setConfig()")
if not self.__config:
base_conf = self.__initializeConfig()
conf = self.__checkDbConnection(app_config)
app_config = toml.dumps(app_config)
- if conf:
+ if conf:
app_config = base_conf + app_config
self.__config = toml.loads(app_config)
self.__saveConfig()
@@ -65,45 +60,41 @@ class ConfigLoader(QObject):
conf = conf + f"ENCRYPTION_KEY = \"{self.__encrypt_key}\"\n\n"
return conf
- def __checkDbConnection(self, db_config):
- # print(f"In {__file__} file, __checkDbConnection()")
- con = DbManager(db_config['database']).getConnection()
- if con:
+ def __checkDbConnection(self):
+ if database.is_closed():
self.dbConnectionError.emit("Connection OK", True)
return True
else:
self.dbConnectionError.emit("Connection fehlgeschlagen", False)
return False
-
def __saveConfig(self):
# print(f"In {__file__} file, saveConfig()")
try:
- with open (self.config_dir + '/pyqcrm.toml', 'w') as f:
+ with open(self.config_dir + '/pyqcrm.toml', 'w') as f:
# print(self.__config)
config = Vermasseln().oscarVermasseln(toml.dumps(self.__config))
f.write(config)
except FileNotFoundError:
print("Konnte die Konfiguration nicht speichern.")
-
def __checkAdminUser(self):
# print(f"In {__file__} file, __checkAdminUser()")
result = UserManager().checkAdmin()
if not result:
- #if not result[0][0] == 1:
+ # if not result[0][0] == 1:
self.adminUserError.emit("Kein Admin vorhanden", False)
return False
else:
self.adminUserError.emit("Admin vorhanden", True)
return True
- @Slot(dict, result= bool)
+ @Slot(dict, result=bool)
def addAdminUser(self, user_config):
# print(f"In {__file__} file, addAdminUser()")
admin = UserManager(user_config["user"], PyqcrmFlags.ADMIN).createUser()
if not admin:
- #self.adminNotAvailable.emit()
+ # self.adminNotAvailable.emit()
self.adminUserError.emit("Benutzername nich verfügbar", False)
else:
self.__config['pyqcrm']['ENCRYPTION_KEY_VALID'] = 'Yes'
@@ -111,7 +102,6 @@ class ConfigLoader(QObject):
self.backupEncryptionKey.emit()
return admin
-
@Slot(str, str)
def __saveData(self, recovery_file, recovery_password, data):
# print(f"In {__file__} file, __saveData()")
@@ -121,7 +111,7 @@ class ConfigLoader(QObject):
rf = Vermasseln().oscarVermasseln(rf, local)
rec_file = urlparse(recovery_file)
if os.name == "nt":
- rec_file = rec_file [1:]
+ rec_file = rec_file[1:]
else:
rec_file = rec_file.path + ".pyqrec"
try:
@@ -136,7 +126,7 @@ class ConfigLoader(QObject):
rec_file = urlparse(recovery_file)
rec_file = rec_file.path
if os.name == "nt":
- rec_file = rec_file [1:]
+ rec_file = rec_file[1:]
try:
ek = self.__parseImport(rec_file, recovery_password)
@@ -165,7 +155,6 @@ class ConfigLoader(QObject):
else:
return None
-
def __invalidateEncryptionKey(self):
# print(f"In {__file__} file, __invalidateEncryptionKey()")
self.__config['pyqcrm']['ENCRYPTION_KEY_VALID'] = 'No'
@@ -182,7 +171,7 @@ class ConfigLoader(QObject):
rp = self.__setRecoveryPassword(recovery_password, salt)
return rp[1] == password
- @Slot(str, str) # todo: non local encryption
+ @Slot(str, str) # todo: non local encryption
def importConfig(self, confile, password):
confile = urlparse(confile)
confile = confile.path
@@ -200,15 +189,10 @@ class ConfigLoader(QObject):
except Exception as e:
print(str(e))
-
-
-
-
-
def __configLoad(self):
# print(f"In {__file__} file, __configLoad()")
try:
- with open (self.config_dir + '/pyqcrm.toml', 'r') as f:
+ with open(self.config_dir + '/pyqcrm.toml', 'r') as f:
config = f.read()
self.__config = toml.loads(Vermasseln().entschluesseln(config))
self.configurationReady.emit()
@@ -219,13 +203,12 @@ class ConfigLoader(QObject):
except Exception as e:
print(str(e))
-
def getConfig(self):
# print(f"In {__file__} file, getConfig()")
# print(self.__config)
return self.__config
- def __setRecoveryPassword(self, key, salt = None):
+ def __setRecoveryPassword(self, key, salt=None):
# print(f"In {__file__} file, __setRecoveryPassword()")
key = Vermasseln.userPasswordHash(key, salt)
return key.split("$")
@@ -242,13 +225,12 @@ class ConfigLoader(QObject):
conf_file = toml.dumps(self.getConfig())
self.__saveData(filename, password, conf_file)
-
@Slot(dict)
- def saveDbConf(self, db = None):
+ def saveDbConf(self, db=None):
self.__config.update(db)
self.__saveConfig()
- @Slot(result = dict)
+ @Slot(result=dict)
def getDbConf(self):
try:
return self.__config['database']
@@ -257,11 +239,11 @@ class ConfigLoader(QObject):
return None
@Slot(dict)
- def saveCompanyInfo(self, company = None):
+ def saveCompanyInfo(self, company=None):
self.__config.update(company)
self.__saveConfig()
- @Slot(result = dict)
+ @Slot(result=dict)
def getCompanyInfo(self):
try:
return self.__config['company']
@@ -270,11 +252,11 @@ class ConfigLoader(QObject):
return None
@Slot(dict)
- def saveMiscConf(self, misc_conf = None):
+ def saveMiscConf(self, misc_conf=None):
self.__config.update(misc_conf)
self.__saveConfig()
- @Slot(result = bool)
+ @Slot(result=bool)
def systray(self):
try:
return self.__config['misc']['SYSTRAY']
@@ -282,9 +264,7 @@ class ConfigLoader(QObject):
print(f"Missing configuration: {ex}")
return False
-
@Slot(str, str)
def backupEncryptkey(self, filename, password):
encrypt_key = self.__config['pyqcrm']['ENCRYPTION_KEY']
self.__saveData(filename, password, encrypt_key)
-
diff --git a/lib/DB/AddressDAO.py b/lib/DB/AddressDAO.py
index b2150bd..4df355b 100644
--- a/lib/DB/AddressDAO.py
+++ b/lib/DB/AddressDAO.py
@@ -1,27 +1,26 @@
-from .DbManager import DbManager
-import mariadb
import json
+import mariadb
+
+from lib.domain.BaseModel import database
+
class AddressDAO:
__cur = None
+
def __init__(self):
- #print(f"*** File: {__file__}, init()")
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
if self.__con:
self.__cur = self.__con.cursor()
-
-
-
def __importPlz(self):
with open("pfad zur datei", "r") as plz:
postcodes = json.load(plz)
irgendwas = ""
try:
for i in postcodes:
- test =i["plz_name"].split(",")
+ test = i["plz_name"].split(",")
for town in test:
if "u.a" in town:
town = town[:-4]
@@ -29,12 +28,12 @@ class AddressDAO:
if town:
print(f"PROCESSING {i['name']} {town}")
self.__cur.callproc("addZipCodes", (i["name"], town, irgendwas,))
- #self.__cur.callproc("addZipCodes", ("56271", "Kleinmaischeid", irgendwas,))
+ # self.__cur.callproc("addZipCodes", ("56271", "Kleinmaischeid", irgendwas,))
except mariadb.OperationalError as e:
print(f"Database Error: {e}")
finally:
self.__con.commit()
- print("FINISHED")#
+ print("FINISHED") #
def __importCountry(self):
with open("pfad zur datei", "r") as country:
@@ -55,18 +54,17 @@ class AddressDAO:
print(i[4], i[3], i[2], i[8], i[7])
- self.__cur.execute("INSERT INTO country (country, countryshort, nationality, iso2, iso3) VALUES (%s, %s, %s, %s, %s)", (i[4], i[3], i[2], i[8], i[7]))
+ self.__cur.execute(
+ "INSERT INTO country (country, countryshort, nationality, iso2, iso3) VALUES (%s, %s, %s, %s, %s)",
+ (i[4], i[3], i[2], i[8], i[7]))
old = i[4]
except mariadb.OperationalError as e:
print(f"Database Error: {e}")
finally:
self.__con.commit()
- print("FINISHED")#
+ print("FINISHED") #
-
-
-
- def getAddressData(self, all = True, zipcode = None):
+ def getAddressData(self, all=True, zipcode=None):
try:
if self.__cur:
self.__cur.callproc("getAddress", (all, zipcode,))
@@ -76,5 +74,3 @@ class AddressDAO:
return None
except mariadb.Error as e:
print(str(e))
-
-
diff --git a/lib/DB/AddressModel.py b/lib/DB/AddressModel.py
index aecd12f..357e8bd 100644
--- a/lib/DB/AddressModel.py
+++ b/lib/DB/AddressModel.py
@@ -2,18 +2,19 @@ from PySide6.QtCore import QAbstractListModel, Qt, Slot, QModelIndex
from .AddressDAO import AddressDAO
from ..PyqcrmDataRoles import PyqcrmDataRoles
+
class AddressModel(QAbstractListModel):
def __init__(self):
super().__init__()
self.__address_data = AddressDAO().getAddressData()
- def rowCount(self, parent = QModelIndex()):
+ def rowCount(self, parent=QModelIndex()):
return len(self.__address_data)
- def data(self, index, role = Qt.DisplayRole):
+ def data(self, index, role=Qt.ItemDataRole.DisplayRole):
row = index.row()
- if role == Qt.DisplayRole:
+ if role == Qt.ItemDataRole.DisplayRole:
data = self.__address_data[row][2]
return data
elif role == PyqcrmDataRoles.CITY_ROLE:
@@ -23,7 +24,7 @@ class AddressModel(QAbstractListModel):
def roleNames(self):
return {
- Qt.DisplayRole: b"display",
+ Qt.ItemDataRole.DisplayRole: b"display",
PyqcrmDataRoles.CITY_ROLE: b"city",
}
@@ -34,9 +35,3 @@ class AddressModel(QAbstractListModel):
def getAddresses(self, all, zipcode):
data = AddressDAO().getAddressData(all, zipcode)
return data
-
-
-
-
-
-
diff --git a/lib/DB/ApplicantModel.py b/lib/DB/ApplicantModel.py
new file mode 100644
index 0000000..48745a5
--- /dev/null
+++ b/lib/DB/ApplicantModel.py
@@ -0,0 +1,76 @@
+import uuid
+from typing import List, Callable, Any
+
+from PySide6.QtCore import QModelIndex, Qt, QAbstractTableModel, Slot
+from PySide6.QtQml import QJSValue
+from peewee import Select
+
+from lib.domain.Applicant import Applicant
+
+COLUMNS: list[Callable[[Applicant], Any]] = [
+ lambda applicant: applicant.first_name,
+ lambda applicant: applicant.last_name,
+ lambda applicant: applicant.zip_code.zip_code or None,
+ lambda applicant: applicant.zip_code.town.town if applicant.zip_code.id is not None else None
+]
+
+COLUMN_NAMES = ["Vorname", "Nachname", "PLZ", "Ort"]
+
+
+class ApplicantModel(QAbstractTableModel):
+ _applicants: Select
+
+ def __init__(self) -> None:
+ super().__init__()
+ self._applicants = Applicant.select_table_data()
+
+ def rowCount(self, /, parent=...):
+ return len(self._applicants)
+
+ def columnCount(self, /, parent=...):
+ return len(COLUMNS)
+
+ def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
+ if role == Qt.ItemDataRole.DisplayRole:
+ applicant = self._applicants[index.row()]
+ return COLUMNS[index.column()](applicant)
+ return None
+
+ @Slot(int, result=dict)
+ def applicant(self, row) -> dict:
+ applicant = Applicant.get_by_id(self._applicants[row].id)
+ return {
+ 'title': applicant.title,
+ "firstName": applicant.first_name,
+ "lastName": applicant.last_name,
+ "street": applicant.street,
+ "houseNumber": applicant.house_number,
+ "zipCode": applicant.zip_code_id,
+ "phoneNumber": applicant.phone_number,
+ "mobileNumber": applicant.mobile_number,
+ "emailAddress": applicant.email_address,
+ "salutation": applicant.salutation
+ }
+
+ @Slot(QJSValue)
+ def createApplicant(self, values: QJSValue):
+ applicant = Applicant()
+ applicant.id = uuid.uuid4()
+ applicant.title = values.property("title").toInt()
+ applicant.first_name = values.property("firstName").toString()
+ applicant.last_name = values.property("lastName").toString()
+ applicant.street = values.property("street").toString() or None
+ applicant.house_number = values.property("houseNumber").toString() or None
+ if values.property("zipCode").toInt() != -1:
+ applicant.zip_code = values.property("zipCode").toInt()
+ applicant.phone_number = values.property("phoneNumber").toString() or None
+ applicant.mobile_number = values.property("mobileNumber").toString() or None
+ applicant.email_address = values.property("emailAddress").toString() or None
+ applicant.salutation = values.property("salutation").toString() or None
+ applicant.save(force_insert=True)
+ self._applicants = Applicant.select_table_data()
+
+ def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.ItemDataRole.DisplayRole):
+ if role == Qt.ItemDataRole.DisplayRole:
+ return COLUMN_NAMES[section]
+ return None
diff --git a/lib/DB/BTypeDAO.py b/lib/DB/BTypeDAO.py
index 6e82db5..d43039b 100644
--- a/lib/DB/BTypeDAO.py
+++ b/lib/DB/BTypeDAO.py
@@ -1,20 +1,20 @@
-from .DbManager import DbManager
+from lib.domain.BaseModel import database
class BTypeDAO:
__cur = None
+
def __init__(self):
- #print(f"*** File: {__file__}, init()")
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
if self.__con:
self.__cur = self.__con.cursor()
def getBType(self):
try:
if self.__cur:
- self.__cur.callproc("getBtype", (None, None, ))
+ self.__cur.callproc("getBtype", (None, None,))
data = self.__cur.fetchall()
- return(data)
+ return data
else:
return None
except mariadb.Error as e:
diff --git a/lib/DB/BusinessDAO.py b/lib/DB/BusinessDAO.py
index d9009c1..557fa24 100644
--- a/lib/DB/BusinessDAO.py
+++ b/lib/DB/BusinessDAO.py
@@ -1,7 +1,7 @@
-from .DbManager import DbManager
import json
import mariadb
from PySide6.QtCore import QObject, Signal
+from lib.domain.BaseModel import database
class BusinessDAO(QObject):
@@ -12,11 +12,11 @@ class BusinessDAO(QObject):
def __init__(self):
super().__init__()
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
if self.__con:
self.__cur = self.__con.cursor()
- def getBusiness(self, enc_key, criterion = "Alle"):
+ def getBusiness(self, enc_key, criterion="Alle"):
try:
if self.__cur:
self.__cur.callproc("getCustomerView", (enc_key, criterion,))
@@ -27,14 +27,14 @@ class BusinessDAO(QObject):
except mariadb.Error as e:
print(str(e))
- def getOneBusiness(self, business_id, enc_key = None):
+ def getOneBusiness(self, business_id, enc_key=None):
try:
if self.__cur:
self.__cur.callproc("getCustomer", (business_id, enc_key,))
- #self.__all_cols = [desc[0] for desc in self.__cur.description]
- return self.__cur.fetchall() #, self.__all_cols
+ # self.__all_cols = [desc[0] for desc in self.__cur.description]
+ return self.__cur.fetchall() # , self.__all_cols
else:
- return None #, None
+ return None # , None
except mariadb.Error as e:
print(str(e))
@@ -47,10 +47,3 @@ class BusinessDAO(QObject):
except mariadb.Error as e:
print(str(e))
-
-
-
-
-
-
-
diff --git a/lib/DB/ContactDAO.py b/lib/DB/ContactDAO.py
index 47ce47c..9acc907 100644
--- a/lib/DB/ContactDAO.py
+++ b/lib/DB/ContactDAO.py
@@ -1,7 +1,9 @@
-from .DbManager import DbManager
-from PySide6.QtCore import QObject, Signal
import json
+
import mariadb
+from PySide6.QtCore import QObject, Signal
+
+from lib.domain.BaseModel import database
class ContactDAO(QObject):
@@ -9,8 +11,7 @@ class ContactDAO(QObject):
def __init__(self):
super().__init__()
- #print(f"*** File: {__file__}, __init__()")
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
if self.__con:
self.__cur = self.__con.cursor()
diff --git a/lib/DB/DbManager.py b/lib/DB/DbManager.py
deleted file mode 100644
index c46c6c5..0000000
--- a/lib/DB/DbManager.py
+++ /dev/null
@@ -1,46 +0,0 @@
-import mariadb
-
-class DbManager():
- __connection = None
- __con_param = None
- __dbmanager = None
-
- def __new__(cls, dbconf = None):
-
- if cls.__dbmanager is None:
- cls.__dbmanager = super(DbManager, cls).__new__(cls)
- cls.__dbmanager.__initializeConfig(dbconf)
-
- return cls.__dbmanager
-
- def getConnection(cls):
- #print(f"DB Manager: {cls.__dbmanager}")
- #print(f"DB Connection: {cls.__connection}")
- try:
- if not cls.__connection or not cls.__connection.ping():
- cls.__failure_notified = False
- cls.__connection = mariadb.connect(**cls.__con_param)
- except mariadb.InterfaceError as e:
- cls.__connection = mariadb.connect(**cls.__con_param)
- print(f"DbManager Connection (INTERFACE ERROR): {e}..reconnecting...")
- except mariadb.Error as e:
- if '(110)' in str(e):
- print(f"File: {__file__}\n Database connection timed out (Check connection parameters or server running): {e}")
- elif '(138)' in str(e):
- print(f"File: {__file__}\n Database connection timed out (Check connection parameters or server running - initial handshake): {e}")
- else:
- print(f"File: {__file__}\n Database connection error: {e}")
- cls.__connection = None
-
- return cls.__connection
-
- def __initializeConfig(cls, dbconf):
- cls.__con_param = { 'user': dbconf['DB_USER'], 'password': dbconf['DB_PASS'],
- 'port': int (dbconf['DB_PORT']), 'host': dbconf['DB_HOST'],
- 'database': dbconf['DB_NAME'], 'connect_timeout': 5, 'autocommit': True,
- }
-
-
-
-
-
diff --git a/lib/DB/EmployeeDAO.py b/lib/DB/EmployeeDAO.py
index b7955a7..d689bd4 100644
--- a/lib/DB/EmployeeDAO.py
+++ b/lib/DB/EmployeeDAO.py
@@ -1,35 +1,41 @@
-from .DbManager import DbManager
import json
-import mariadb
+
from PySide6.QtCore import QObject, Signal
+from lib.domain.BaseModel import database
+
class EmployeeDAO(QObject):
newEmployeeAdded = Signal(bool)
- __all_cols = None
def __init__(self):
super().__init__()
- self.__con = DbManager().getConnection()
+ self._connection = database.connection()
def getEmployees(self, enc_key, criterion="Alle", processed=False, fired=False, every_state=True):
- cursor = self.__con.cursor()
- cursor.callproc("getEmployeeTable", (criterion, processed, fired, every_state, enc_key,))
- self.__all_cols = [desc[0] for desc in cursor.description]
- result = cursor.fetchall(), self.__all_cols
- cursor.close()
- return result
+ cursor = self._connection.cursor()
+ try:
+ cursor.callproc("getEmployeeTable", (criterion, processed, fired, every_state, enc_key,))
+ all_cols = [desc[0] for desc in cursor.description]
+ result = cursor.fetchall(), all_cols
+ return result
+ finally:
+ cursor.close()
def fetchApplicant(self, employee_id, enc_key=None) -> dict:
- cursor = self.__con.cursor(dictionary=True)
- cursor.callproc("getApplicant", (employee_id, enc_key))
- it = cursor.fetchone()
- cursor.close()
- return it
+ cursor = self._connection.cursor(dictionary=True)
+ try:
+ cursor.callproc("getApplicant", (employee_id, enc_key))
+ it = cursor.fetchone()
+ return it
+ finally:
+ cursor.close()
- def addEmployee(self, data, enc_key, applicant=True):
- cursor = self.__con.cursor()
- cursor.callproc("addApplicant", (json.dumps(data), applicant, enc_key,))
- self.__con.commit()
- cursor.close()
- self.newEmployeeAdded.emit(True)
+ def addApplicant(self, data, enc_key, applicant=True):
+ cursor = self._connection.cursor()
+ try:
+ cursor.callproc("addApplicant", (json.dumps(data), applicant, enc_key,))
+ self._connection.commit()
+ self.newEmployeeAdded.emit(True)
+ finally:
+ cursor.close()
diff --git a/lib/DB/EmployeeModel.py b/lib/DB/EmployeeModel.py
index 00e85af..ae60437 100644
--- a/lib/DB/EmployeeModel.py
+++ b/lib/DB/EmployeeModel.py
@@ -10,7 +10,6 @@ class EmployeeModel(QAbstractTableModel):
addedNewEmployee = Signal(bool)
__data = None
__employee_dao = None
- __visible_index = None
__visible_columns = None
__col_name = ""
__col_skip = 2
@@ -18,7 +17,7 @@ class EmployeeModel(QAbstractTableModel):
def __init__(self):
super().__init__()
- self.__employee_dao = EmployeeDAO()
+ self.__employee_dao = EmployeeDAO()
self.__employee_dao.newEmployeeAdded.connect(self.__refreshView)
self.__conf = ConfigLoader().getConfig()
self.__key = self.__conf['pyqcrm']['ENCRYPTION_KEY']
@@ -29,11 +28,11 @@ class EmployeeModel(QAbstractTableModel):
if 'worklicense' in new_employee:
new_employee['worklicense'] = int(new_employee['worklicense'])
new_employee['residencetype'] = int(new_employee['residencetype'])
- self.__employee_dao.addEmployee(new_employee, self.__key, False)
+ self.__employee_dao.addApplicant(new_employee, self.__key, False)
@Slot(QJSValue)
def addApplicant(self, applicant: QJSValue):
- self.__employee_dao.addEmployee({
+ self.__employee_dao.addApplicant({
"city": applicant.property("city").toString(),
"email": applicant.property("email").toString(),
"firstname": applicant.property("firstname").toString(),
@@ -72,29 +71,21 @@ class EmployeeModel(QAbstractTableModel):
self.__col_skip = 2
self.__getData(criterion, criterion == 'Erledigt', False, criterion == 'Alle')
- def data(self, index, role=Qt.DisplayRole):
- if role == Qt.DisplayRole:
+ def data(self, index, role=Qt.ItemDataRole.DisplayRole):
+ if role == Qt.ItemDataRole.DisplayRole:
row = self.__data[index.row()]
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 applicant_col == 2 and self.__everyone:
tr = 'Ja' if tr == 1 else 'Nein'
else:
if tr:
tr = re.sub("Keine Angabe ", "", tr)
- # print(f"Data: {tr}")
- # return row[index.column() + 2]
return tr
return None
- def headerData(self, section, orientation, role=Qt.DisplayRole):
- if orientation == Qt.Horizontal and role == Qt.DisplayRole:
+ def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole):
+ if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole:
self.__col_name = self.__visible_columns[section + self.__col_skip]
return self.__col_name
return super().headerData(section, orientation, role)
-
- @Slot(int, result=dict)
- def fetchApplicant(self, row) -> dict:
- employee_id = self.__data[row][0]
- return self.__employee_dao.fetchApplicant(employee_id, self.__key)
diff --git a/lib/DB/ObjectDAO.py b/lib/DB/ObjectDAO.py
index dea84c1..114c24b 100644
--- a/lib/DB/ObjectDAO.py
+++ b/lib/DB/ObjectDAO.py
@@ -1,17 +1,14 @@
-from .DbManager import DbManager
import json
import mariadb
from PySide6.QtCore import QObject, Signal
-# from ..PyqcrmFlags import PyqcrmAppliEmpyFlags
-
+from lib.domain.BaseModel import database
class ObjectDAO(QObject):
newObjectAdded = Signal(bool, int)
def __init__(self):
super().__init__()
- #print(f"*** File: {__file__}, __init__()")
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
if self.__con:
self.__cur = self.__con.cursor()
diff --git a/lib/DB/UserDAO.py b/lib/DB/UserDAO.py
index aedb459..6058338 100644
--- a/lib/DB/UserDAO.py
+++ b/lib/DB/UserDAO.py
@@ -1,20 +1,21 @@
# This Python file uses the following encoding: utf-8
-from .DbManager import DbManager
from ..PyqcrmFlags import PyqcrmFlags
import mariadb
from PySide6.QtCore import QObject, Signal
+from lib.domain.BaseModel import database
+
class UserDAO(QObject):
noDbConnection = Signal(str)
__cursor = None
+
def __init__(self):
- #print(f"*** File: {__file__}, init()")
super().__init__()
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
if self.__con:
self.__cur = self.__con.cursor()
- def createUser(self, username, password, info, role= PyqcrmFlags.USER):
+ def createUser(self, username, password, info, role=PyqcrmFlags.USER):
user_created = False
try:
if self.__cur:
@@ -39,6 +40,3 @@ class UserDAO(QObject):
except mariadb.Error as e:
print(str(e))
self.noDbConnection.emit(str(e))
-
-
-
diff --git a/lib/DB/UserManager.py b/lib/DB/UserManager.py
index dd8b5f6..37f1f6d 100644
--- a/lib/DB/UserManager.py
+++ b/lib/DB/UserManager.py
@@ -1,35 +1,28 @@
-from .DbManager import DbManager
+from PySide6.QtCore import Slot, QObject, Signal
+
+from lib.domain.BaseModel import database
+from .UserDAO import UserDAO
from ..PyqcrmFlags import PyqcrmFlags
from ..Vermasseln import Vermasseln
-#from PySide6.QtMultimedia import QMediaPlayer, QAudioOutput : Not working well with Nuitka
-import soundfile as sf
-import sounddevice as sd
-from .UserDAO import UserDAO
-from PySide6.QtCore import Slot, QObject, Signal, QUrl, QFile
-import tempfile
-
class UserManager(QObject):
-
loginOkay = Signal()
noDbConnection = Signal(str)
- def __init__(self, user_config = None, role = None):
+ def __init__(self, user_config=None, role=None):
super().__init__()
- self.__con = DbManager().getConnection()
+ self.__con = database.connection()
self.__user_dao = UserDAO()
self.__user_dao.noDbConnection.connect(self.noDbConnection)
if self.__con:
self.__cur = self.__con.cursor()
if user_config and role:
-
self.__username = user_config["PYQCRM_USER"]
self.__password = user_config["PYQCRM_USER_PASS"]
self.__info = user_config["PYQCRM_USER_INFO"]
self.__role = role if role == PyqcrmFlags.ADMIN else 0
-
def createUser(self):
self.__hashPassword()
user_created = self.__user_dao.createUser(self.__username, self.__password, self.__info, self.__role)
@@ -64,25 +57,6 @@ class UserManager(QObject):
user = self.__user_dao.getUser(username)
if user:
self.__checkPassword(password, user[2])
- else:
- fail_src = ":/sounds/fail2c.ogg"
- with tempfile.NamedTemporaryFile(suffix='.ogg') as ogg_file:
- failure_sound = QFile(fail_src)
- if not failure_sound.open(QFile.ReadOnly):
- print(f"Failed to open resource file: {fail_src}")
- else:
- ogg_file.write(failure_sound.readAll())
- ogg_path = ogg_file.name
- fail, samplerate = sf.read(ogg_path)
- sd.play(fail, samplerate)
-
- ### Not working with Nuitka
- # player = QMediaPlayer(self)
- # audioOutput = QAudioOutput(self)
- # player.setAudioOutput(audioOutput)
- # player.setSource(QUrl("qrc:/sounds/fail2c.ogg"))
- # audioOutput.setVolume(150)
- # player.play()
def __checkPassword(self, password, hash_password):
pw_list = hash_password.split("$")
@@ -90,6 +64,3 @@ class UserManager(QObject):
hash_pw = Vermasseln.userPasswordHash(password, pw_list[0])
if hash_password == hash_pw:
self.loginOkay.emit()
-
-
-
diff --git a/lib/domain/Applicant.py b/lib/domain/Applicant.py
new file mode 100644
index 0000000..0fa4425
--- /dev/null
+++ b/lib/domain/Applicant.py
@@ -0,0 +1,31 @@
+from peewee import CharField, UUIDField, SmallIntegerField, TextField, ForeignKeyField, JOIN
+
+from lib.domain.Town import Town
+from lib.domain.BaseModel import BaseModel
+from lib.domain.ZipCode import ZipCode
+
+
+class Applicant(BaseModel):
+ class Meta:
+ table_name = "applicants"
+
+ id = UUIDField(primary_key=True)
+ title = SmallIntegerField(default=0)
+ first_name = CharField(null=False)
+ last_name = CharField(null=False)
+ street = CharField()
+ house_number = CharField()
+ zip_code = ForeignKeyField(ZipCode, column_name="zip_code", null=True)
+ phone_number = CharField()
+ mobile_number = CharField()
+ email_address = CharField()
+ salutation = TextField(null=False)
+
+ @classmethod
+ def select_table_data(cls):
+ return (
+ Applicant
+ .select(Applicant.id, Applicant.first_name, Applicant.last_name, ZipCode.id, ZipCode.zip_code, Town.town)
+ .join(ZipCode, join_type="LEFT JOIN")
+ .join(Town, join_type="LEFT JOIN")
+ )
diff --git a/lib/domain/BaseModel.py b/lib/domain/BaseModel.py
new file mode 100644
index 0000000..56bac14
--- /dev/null
+++ b/lib/domain/BaseModel.py
@@ -0,0 +1,8 @@
+from peewee import Model, MySQLDatabase
+
+database = MySQLDatabase(None)
+
+
+class BaseModel(Model):
+ class Meta:
+ database = database
diff --git a/lib/domain/Country.py b/lib/domain/Country.py
new file mode 100644
index 0000000..79a068a
--- /dev/null
+++ b/lib/domain/Country.py
@@ -0,0 +1,14 @@
+from peewee import AutoField, CharField
+
+from lib.domain.BaseModel import BaseModel
+
+
+class Country(BaseModel):
+ class Meta:
+ table_name = "country"
+ id = AutoField(column_name="countryid")
+ name = CharField(max_length=200, unique=True)
+ name_short = CharField(max_length=100, column_name="countryshort")
+ nationality = CharField(max_length=100)
+ iso2 = CharField(max_length=2, unique=True)
+ iso3 = CharField(max_length=3, unique=True)
diff --git a/lib/domain/Town.py b/lib/domain/Town.py
new file mode 100644
index 0000000..44bdda9
--- /dev/null
+++ b/lib/domain/Town.py
@@ -0,0 +1,12 @@
+from peewee import AutoField, CharField, ForeignKeyField
+
+from lib.domain.BaseModel import BaseModel
+from lib.domain.Country import Country
+
+
+class Town(BaseModel):
+ class Meta:
+ table_name = "address"
+ id = AutoField(column_name="addressid")
+ town = CharField(max_length=50, column_name="city")
+ country = ForeignKeyField(Country, column_name="countryid", backref="towns")
diff --git a/lib/domain/ZipCode.py b/lib/domain/ZipCode.py
new file mode 100644
index 0000000..0a0e26c
--- /dev/null
+++ b/lib/domain/ZipCode.py
@@ -0,0 +1,13 @@
+from peewee import AutoField, CharField, ForeignKeyField
+
+from lib.domain.BaseModel import BaseModel
+from lib.domain.Town import Town
+
+
+class ZipCode(BaseModel):
+ class Meta:
+ table_name = "postcode"
+
+ id = AutoField(column_name="postcodeid")
+ zip_code = CharField(max_length=15, column_name="postcode")
+ town = ForeignKeyField(Town, backref="zip_codes", column_name="addressid")
diff --git a/main.py b/main.py
index 7fa4103..c16c89f 100644
--- a/main.py
+++ b/main.py
@@ -1,44 +1,35 @@
# # !/home/linuxero/proj/tero/pyqcrm/.qtcreator/venv-3.13.1/bin/python3
import os
import sys
-import logging
-from PySide6.QtNetwork import QLocalServer, QLocalSocket
-from PySide6.QtWidgets import QSystemTrayIcon
-from PySide6.QtGui import QGuiApplication, QIcon
-from PySide6.QtQml import QQmlApplicationEngine
-from PySide6.QtCore import QIODevice
-from lib.ConfigLoader import ConfigLoader
-from lib.DB.BusinessModel import BusinessModel
+# noinspection PyUnresolvedReferences
import rc_pyqcrm
+# noinspection PyUnresolvedReferences
import rc_qml
-from lib.DB.DbManager import DbManager
-from lib.DB.UserManager import UserManager
+
+from PySide6.QtCore import QIODevice
+from PySide6.QtGui import QGuiApplication, QIcon
+from PySide6.QtNetwork import QLocalServer, QLocalSocket
+from PySide6.QtQml import QQmlApplicationEngine
+from PySide6.QtWidgets import QSystemTrayIcon
+
+from lib.ConfigLoader import ConfigLoader
from lib.DB.AddressModel import AddressModel
+from lib.DB.ApplicantModel import ApplicantModel
from lib.DB.BTypeModel import BTypeModel
+from lib.DB.BusinessModel import BusinessModel
from lib.DB.ContactModel import ContactModel
from lib.DB.EmployeeModel import EmployeeModel
from lib.DB.ObjectModel import ObjectModel
+from lib.DB.UserManager import UserManager
from lib.Printers import Printers
+from lib.domain.BaseModel import database
os.environ['QML_XHR_ALLOW_FILE_READ'] = '1'
-
-# [pyqcrm]
-# program-name=""
-# version=
-
-# [database]
-# server=""
-# port=
-# user=""
-# password=""
-# name=""
-# type=""
-
-
bad_config = False
db_con = False
address_model = None
+applicant_model = None
business_model = None
business_type = None
contact_model = None
@@ -49,17 +40,26 @@ user = None
def initializeProgram():
- print(f"In {__file__} file, initializeProgram()")
- global address_model, bad_config, business_model, user, business_type, contact_model, employee_model, object_model, db_con, printers
+ global address_model, applicant_model, bad_config, business_model, user, business_type, contact_model, employee_model, object_model, db_con, printers
if not bad_config:
dbconf = config.getConfig()['database']
- DbManager(dbconf)
+ database.init(
+ host=dbconf['DB_HOST'],
+ user=dbconf['DB_USER'],
+ password=dbconf['DB_PASS'],
+ database=dbconf['DB_NAME'],
+ port=int(dbconf['DB_PORT']),
+ connect_timeout=5,
+ )
+ database.connect()
+
printers = Printers()
- if DbManager().getConnection():
+ if not database.is_closed():
db_con = True
user = UserManager()
business_model = BusinessModel()
address_model = AddressModel()
+ applicant_model = ApplicantModel()
business_type = BTypeModel()
contact_model = ContactModel()
employee_model = EmployeeModel()
@@ -74,11 +74,11 @@ def configReady():
def publishContext():
- # print(f"In {__file__} file, publishContext()")
- global engine, address_model, bad_config, business_model, user, business_type, contact_model, object_model, employee_model, printers
+ global engine, address_model, applicant_model, bad_config, business_model, user, business_type, contact_model, object_model, employee_model, printers
engine.rootContext().setContextProperty("loggedin_user", user)
engine.rootContext().setContextProperty("business_model", business_model)
engine.rootContext().setContextProperty("address_model", address_model)
+ engine.rootContext().setContextProperty("applicantModel", applicant_model)
engine.rootContext().setContextProperty("business_type", business_type)
engine.rootContext().setContextProperty("contact_model", contact_model)
engine.rootContext().setContextProperty("employee_model", employee_model)
@@ -105,7 +105,7 @@ if __name__ == "__main__":
qml_file = "qrc:/Gui/main.qml"
- icon = QIcon(":/images/tero.jpg")
+ icon = QIcon("qrc:/images/tero.jpg")
app.setWindowIcon(icon)
tray = QSystemTrayIcon()
diff --git a/pyqcrm.pyproject b/pyqcrm.pyproject
index 7db28ab..9f3ccb6 100644
--- a/pyqcrm.pyproject
+++ b/pyqcrm.pyproject
@@ -7,7 +7,6 @@
"lib/DB/BusinessModel.py",
"pyqcrm.qrc",
"qml.qrc",
- "lib/DB/DbManager.py",
"lib/DB/UserManager.py",
"lib/PyqcrmFlags.py",
"lib/DB/UserDAO.py",
diff --git a/pyqcrm.qrc b/pyqcrm.qrc
index 1927922..b3e221d 100644
--- a/pyqcrm.qrc
+++ b/pyqcrm.qrc
@@ -9,6 +9,7 @@
images/ChevronDown.svg
images/Funnel.svg
images/Identification-Outline.svg
+ images/InboxArrowDown.svg
images/MagnifyingGlass.svg
images/Newspaper-Outline.svg
images/Phone.svg
@@ -19,14 +20,8 @@
images/UserCircle.svg
images/UserGroup-Outline.svg
images/Wallet-Outline.svg
- sounds/error.ogg
- sounds/fail2c.ogg
- sounds/puzzerr.ogg
- sounds/sysnotify.ogg
- sounds/wrong.ogg
fonts/RobotoCondensed.otf
README
LICENSE
- images/tero.jpg
diff --git a/qml.qrc b/qml.qrc
index 9d1b12c..b078986 100644
--- a/qml.qrc
+++ b/qml.qrc
@@ -39,11 +39,11 @@
Gui/OffersTable.qml
Gui/Employees/AddApplicant.qml
Gui/Employees/AddEmployee.qml
- Gui/Employees/ApplicantPersonalData.qml
- Gui/Employees/ApplicantBankData.qml
Gui/Employees/ApplicantForm.qml
- Gui/Employees/ApplicantNationalInsurance.qml
- Gui/Employees/ApplicantVarious.qml
+ Gui/Employees/EmployeePersonalData.qml
+ Gui/Employees/EmployeeBankData.qml
+ Gui/Employees/EmployeeNationalInsurance.qml
+ Gui/Employees/EmployeeVarious.qml
Gui/Employees/EmployeeDetails.qml
Gui/Employees/EmployeesTable.qml
Gui/Employees/qmldir
diff --git a/requirements.txt b/requirements.txt
index 7d26b55..f301c49 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,7 +3,8 @@ platformdirs
pycryptodome
psutil
toml
-mariadb
soundfile
sounddevice
reportlab
+peewee
+pymysql
\ No newline at end of file
diff --git a/sounds/error.aac b/sounds/error.aac
deleted file mode 100644
index 1a1fdc7..0000000
Binary files a/sounds/error.aac and /dev/null differ
diff --git a/sounds/error.ac3 b/sounds/error.ac3
deleted file mode 100644
index 5f7f39b..0000000
Binary files a/sounds/error.ac3 and /dev/null differ
diff --git a/sounds/error.mp3 b/sounds/error.mp3
deleted file mode 100644
index ad527eb..0000000
Binary files a/sounds/error.mp3 and /dev/null differ
diff --git a/sounds/error.ogg b/sounds/error.ogg
deleted file mode 100644
index a622fb5..0000000
Binary files a/sounds/error.ogg and /dev/null differ
diff --git a/sounds/error.wav b/sounds/error.wav
deleted file mode 100644
index a184896..0000000
Binary files a/sounds/error.wav and /dev/null differ
diff --git a/sounds/fail2c.ogg b/sounds/fail2c.ogg
deleted file mode 100644
index c18884c..0000000
Binary files a/sounds/fail2c.ogg and /dev/null differ
diff --git a/sounds/puzzerr.ogg b/sounds/puzzerr.ogg
deleted file mode 100644
index fce3b92..0000000
Binary files a/sounds/puzzerr.ogg and /dev/null differ
diff --git a/sounds/sysnotify.ogg b/sounds/sysnotify.ogg
deleted file mode 100644
index 7cc1475..0000000
Binary files a/sounds/sysnotify.ogg and /dev/null differ
diff --git a/sounds/wrong.ogg b/sounds/wrong.ogg
deleted file mode 100644
index ec56a55..0000000
Binary files a/sounds/wrong.ogg and /dev/null differ