Initial
commit
2c52631787
|
|
@ -0,0 +1,3 @@
|
|||
/.py
|
||||
/__pycache__
|
||||
/test
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
from QT import QtWidgets, QtGui, QT
|
||||
from _With_Table_Widget_ import _With_Table_Widget_
|
||||
from App_State import App_State
|
||||
import schema
|
||||
|
||||
class Action_List (_With_Table_Widget_) :
|
||||
|
||||
settings_group = "order-list"
|
||||
Columns = \
|
||||
("Datum", "Benutzer", "Kind", "Text")
|
||||
|
||||
def __init__ (self, actions, parent = None) :
|
||||
super ().__init__ (parent = parent)
|
||||
self._view.setRowCount (len (actions))
|
||||
for row, a in enumerate (actions) :
|
||||
self._add_read_only_string (row, 0, a.date.strftime ("%H:%M:%S %d-%d-%Y"))
|
||||
self._add_read_only_string (row, 1, a.user.username)
|
||||
self._add_read_only_string (row, 2,
|
||||
App_State.Action_Kind [a.action_kind])
|
||||
self._add_read_only_string (row, 3, a.action)
|
||||
header =self._view.horizontalHeader ()
|
||||
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
|
||||
# end def __init__
|
||||
|
||||
# end class Action_List
|
||||
|
||||
class Action_Dialog (QtWidgets.QDialog) :
|
||||
|
||||
def __init__ (self, actions) :
|
||||
super ().__init__ ()
|
||||
self.setMinimumSize (640, 400)
|
||||
l = QtWidgets.QHBoxLayout (self)
|
||||
self.action_list = Action_List (actions)
|
||||
l.addWidget (self.action_list)
|
||||
self.setModal (False)
|
||||
# end def __init__
|
||||
|
||||
|
||||
# end class Action_Dialog
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import schema
|
||||
|
||||
class App_State :
|
||||
|
||||
user_id = None
|
||||
|
||||
Action_Kind = \
|
||||
{ 1 : "Create Order"
|
||||
, 10 : "Change owner"
|
||||
, 20 : "IMOS CAD started"
|
||||
, 25 : "IMOS CAD closed"
|
||||
}
|
||||
@classmethod
|
||||
def Create_Action (cls, kind, text, order = None) :
|
||||
if kind not in cls. Action_Kind :
|
||||
raise ValueError (f"Unknow action kind {kind}")
|
||||
schema.Action \
|
||||
( user = cls.user_id
|
||||
, date = schema.datetime.now ()
|
||||
, action_kind = kind
|
||||
, action = text
|
||||
, order = order
|
||||
)
|
||||
# end def create_action
|
||||
|
||||
# end class App_State
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
from QT import QtWidgets, QT
|
||||
import schema
|
||||
|
||||
|
||||
class Login_Dialog (QtWidgets.QDialog) :
|
||||
|
||||
def __init__ (self, username = "") :
|
||||
super ().__init__ ()
|
||||
self.setWindowTitle ("Login")
|
||||
self.layout = L = QtWidgets.QFormLayout (self)
|
||||
self.user_name = QtWidgets.QLineEdit ()
|
||||
self.password = QtWidgets.QLineEdit ()
|
||||
self.password.setEchoMode (QtWidgets.QLineEdit.Password)
|
||||
L.addRow ("Benutzername", self.user_name)
|
||||
L.addRow ("Passwort", self.password)
|
||||
layout = QtWidgets.QHBoxLayout ()
|
||||
login = QtWidgets.QPushButton ("Login")
|
||||
login.setEnabled (False)
|
||||
self.error = QtWidgets.QLabel ("")
|
||||
layout.addWidget (self.error)
|
||||
login.clicked.connect (self._login)
|
||||
layout.addStretch (10)
|
||||
layout.addWidget (login)
|
||||
login.setDefault (True)
|
||||
L.addRow (layout)
|
||||
self.login = login
|
||||
self.password.editingFinished.connect (self._login)
|
||||
self.user_name.editingFinished.connect(self._check_login_possible)
|
||||
self.user_id = None
|
||||
self.user_name.setText (username)
|
||||
if username :
|
||||
self.password.setFocus ()
|
||||
# end def __init__
|
||||
|
||||
def _check_login_possible (self) :
|
||||
un = self.user_name.text ()
|
||||
pw = self.password.text ()
|
||||
self.login.setEnabled ((len (un) >= 3) and (len (pw) >= 3))
|
||||
# end def _check_login_possible
|
||||
|
||||
def _login (self) :
|
||||
un = self.user_name.text ()
|
||||
pw = self.password.text ()
|
||||
with schema.orm.db_session :
|
||||
user = schema.User.get (username = un)
|
||||
if not user :
|
||||
self.error.setText ("User nicht gefunden")
|
||||
else :
|
||||
if user.check_password (pw) :
|
||||
self.user_id = user.id
|
||||
self.accept ()
|
||||
else :
|
||||
self.error.setText ("Passwort falsch")
|
||||
# end def _login
|
||||
|
||||
# end class Login_Dialog
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
from QT import QtWidgets, QtGui, QT
|
||||
from _With_Table_Widget_ import _With_Table_Widget_
|
||||
from App_State import App_State
|
||||
from Action_List import Action_Dialog
|
||||
import schema
|
||||
import subprocess
|
||||
import threading
|
||||
import time
|
||||
|
||||
class Order_List (_With_Table_Widget_) :
|
||||
|
||||
settings_group = "order-list"
|
||||
Header = "Aufträge"
|
||||
Columns = \
|
||||
("Warenkorb", "Status", "Bearbeiter", "Kommission", "Kunde", "Linie")
|
||||
|
||||
State_Map = \
|
||||
{ 0 : "neu"
|
||||
, 10 : "in Bearbeitung"
|
||||
, 20 : "im CAD geöffnet"
|
||||
, 90 : "Odoo"
|
||||
, 95 : "Zurückgesetzt"
|
||||
, 99 : "Storno"
|
||||
}
|
||||
def __init__ (self, parent = None) :
|
||||
super ().__init__ (parent)
|
||||
self._view.setContextMenuPolicy (QT.CustomContextMenu)
|
||||
self._view.customContextMenuRequested.connect (self._show_context_menu)
|
||||
ACT = QtGui.QAction
|
||||
self._open_cad = ACT (self.tr ("Im CAD öffnen"))
|
||||
self._recreate_cnc = ACT (self.tr ("CNC Programm neu erzeugen"))
|
||||
self._reset_order = ACT (self.tr ("Auftrag zurücksetzen"))
|
||||
self._cancel = ACT (self.tr ("Auftrag stronieren"))
|
||||
self._send_to_odoo = ACT (self.tr ("Auftrag ins Odoo schicken"))
|
||||
self._actions = ACT (self.tr ("Aktionsliste"))
|
||||
self._open_cad.triggered.connect (self._open_order_in_cad)
|
||||
self._recreate_cnc.triggered.connect (self._start_recreate_cnc)
|
||||
self._reset_order.triggered.connect (self._reset_order_in_webshop)
|
||||
self._cancel.triggered.connect (self._cancel_order)
|
||||
self._send_to_odoo.triggered.connect (self._send_oder_to_odoo)
|
||||
self._actions.triggered.connect (self._show_actions)
|
||||
self._cad_processes = {}
|
||||
# end def __init__
|
||||
|
||||
def _show_context_menu (self, pos) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
with schema.orm.db_session () :
|
||||
order = schema.Order.get (basket_no = bno)
|
||||
if order.user and order.user.id != App_State.user_id :
|
||||
r = QtWidgets.QMessageBox.question \
|
||||
( self, self.tr ("Fehler")
|
||||
, self.tr
|
||||
( "Dieser Auftrag wird bereits von jemand anderes "
|
||||
"bearbeitet.\n"
|
||||
"Wollen Sie den Auftrag als Bearbeiter übernehmen?"
|
||||
)
|
||||
)
|
||||
if r == QtWidgets.QMessageBox.No :
|
||||
return
|
||||
App_State.Create_Action \
|
||||
( 10
|
||||
, f"User changed from {order.user.id} to {App_State.user_id}"
|
||||
, order
|
||||
)
|
||||
order.user = schema.User [App_State.user_id]
|
||||
self.update_order (order, False, row_data [0].row ())
|
||||
state = order.state
|
||||
if state < 20 :
|
||||
cm = QtWidgets.QMenu ()
|
||||
cm.addAction (self._open_cad)
|
||||
cm.addAction (self._recreate_cnc)
|
||||
cm.addSeparator ()
|
||||
cm.addAction (self._send_to_odoo)
|
||||
cm.addSeparator ()
|
||||
cm.addAction (self._reset_order)
|
||||
cm.addAction (self._cancel)
|
||||
cm.addSeparator ()
|
||||
cm.addAction (self._actions)
|
||||
cm.exec (self._view.mapToGlobal (pos))
|
||||
# end def _show_context_menu
|
||||
|
||||
def update_order (self, order, new, row = None) :
|
||||
if new :
|
||||
row = self._view.rowCount ()
|
||||
self._view.setRowCount (row + 1)
|
||||
self._add_read_only_string (row, 0, str (order.basket_no))
|
||||
self._add_read_only_string (row, 1, self.State_Map [order.state])
|
||||
if order.user :
|
||||
self._add_read_only_string (row, 2, order.user.username)
|
||||
self._add_read_only_string (row, 3, order.commission)
|
||||
self._add_read_only_string (row, 4, order.imos_user)
|
||||
self._add_read_only_string (row, 5, str (order.production_line))
|
||||
else :
|
||||
if row is None :
|
||||
for row in range (self._view.rowCount ()) :
|
||||
if self._view.item (row, 0).text () == order.basket_no :
|
||||
break
|
||||
else :
|
||||
print ("Could not find order")
|
||||
return
|
||||
self._update_read_only_string (row, 1, self.State_Map [order.state])
|
||||
self._update_read_only_string (row, 2, order.user.username)
|
||||
# end def update_order
|
||||
|
||||
def _open_order_in_cad (self) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
with schema.orm.db_session () :
|
||||
state = schema.State.get ()
|
||||
order = schema.Order.get (basket_no = bno)
|
||||
if order.state < 20 :
|
||||
order.state = 20
|
||||
self.update_order (order, False, row_data [0].row ())
|
||||
self._cad_processes [bno] = subprocess.Popen \
|
||||
( (r"%s\%s\%s.dwg" % (state.imos_order_dir, bno, bno), )
|
||||
, shell = True
|
||||
)
|
||||
threading.Thread \
|
||||
( target = self._wait_for_cad_close
|
||||
, args = (bno, )
|
||||
, daemon = True
|
||||
).start ()
|
||||
App_State.Create_Action \
|
||||
( 20
|
||||
, f"IMOS CAD started {order.basket_no}"
|
||||
, order
|
||||
)
|
||||
# end def _open_order_in_cad
|
||||
|
||||
def _wait_for_cad_close (self, basket_no) :
|
||||
p = self._cad_processes [basket_no]
|
||||
while p.poll () is None :
|
||||
time.sleep (.5)
|
||||
del self._cad_processes [basket_no]
|
||||
with schema.orm.db_session () :
|
||||
order = schema.Order.get (basket_no = basket_no)
|
||||
order.state = 10
|
||||
self.update_order (order, False)
|
||||
App_State.Create_Action \
|
||||
( 25
|
||||
, f"IMOS CAD closed {order.basket_no}"
|
||||
, order
|
||||
)
|
||||
# end def _wait_for_cad_close
|
||||
|
||||
def _start_recreate_cnc (self) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
print (bno)
|
||||
# end def _start_recreate_cnc
|
||||
|
||||
def _reset_order_in_webshop (self) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
print (bno)
|
||||
# end def _reset_order_in_webshop
|
||||
|
||||
def _cancel_order (self) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
print (bno)
|
||||
# end def _cancel_order
|
||||
|
||||
def _send_oder_to_odoo (self) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
print (bno)
|
||||
# end def _send_oder_to_odoo
|
||||
|
||||
def _show_actions (self) :
|
||||
row_data = self._view.selectedItems ()
|
||||
if row_data :
|
||||
bno = row_data [0].text ()
|
||||
with schema.orm.db_session () :
|
||||
order = schema.Order.get (basket_no = bno)
|
||||
Action_Dialog \
|
||||
(order.actions.order_by (schema.orm.desc (schema.Action.date))).exec ()
|
||||
# end def _show_actions
|
||||
|
||||
# end class Order_List
|
||||
|
||||
class Order_Detail (_With_Table_Widget_) :
|
||||
|
||||
settings_group = "order-detail"
|
||||
Header = "Auftrags Detail"
|
||||
Columns = \
|
||||
("Position", "Artikel", "Preis")
|
||||
|
||||
# end class Order_Detail
|
||||
|
||||
class Order_Display (QtWidgets.QSplitter) :
|
||||
|
||||
def __init__ (self, parent) :
|
||||
super ().__init__ (parent)
|
||||
self._order_list = Order_List ()
|
||||
self._order_detail = Order_Detail ()
|
||||
self.addWidget (self._order_list)
|
||||
self.addWidget (self._order_detail)
|
||||
self.orders = {}
|
||||
# end def __init__
|
||||
|
||||
def update_orders (self) :
|
||||
with schema.orm.db_session :
|
||||
for o in schema.Order.select () :
|
||||
db_lc = o.actions.order_by (schema.Action.date).first ().date
|
||||
if o.basket_no not in self.orders :
|
||||
self._order_list.update_order (o, True)
|
||||
self.orders [o.basket_no] = o
|
||||
o.last_changed = db_lc
|
||||
else :
|
||||
if db_lc > self.orders [o.basket_no].last_changed :
|
||||
self._order_list.update_order (o, False)
|
||||
self.orders [o.basket_no].last_changed = db_lc
|
||||
# end def update_orders
|
||||
|
||||
def save_settings (self, settings) :
|
||||
settings.beginGroup ("order-display")
|
||||
settings.setValue ("geometry", self.saveGeometry ())
|
||||
settings.setValue ("windowState", self.saveState ())
|
||||
settings.endGroup ()
|
||||
self._order_list .save_settings (settings)
|
||||
self._order_detail.save_settings (settings)
|
||||
# end def save_settings
|
||||
|
||||
def restore_settings (self, settings) :
|
||||
settings.beginGroup ("order-display")
|
||||
self.restoreGeometry (settings.value ("geometry" ))
|
||||
self.restoreState (settings.value ("windowState"))
|
||||
settings.endGroup ()
|
||||
self._order_list .restore_settings (settings)
|
||||
self._order_detail.restore_settings (settings)
|
||||
# end def restore_settings
|
||||
|
||||
# end class Order_Display
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
from QT import QtWidgets, QT
|
||||
|
||||
class _With_Table_Widget_ (QtWidgets.QWidget) :
|
||||
|
||||
Header = None
|
||||
|
||||
def __init__ (self, parent = None) :
|
||||
super ().__init__ (parent)
|
||||
self._box = QtWidgets.QVBoxLayout (self)
|
||||
if self.Header :
|
||||
header = QtWidgets.QLabel (self.Header)
|
||||
self._box.addWidget (header)
|
||||
self._view = QtWidgets.QTableWidget (0, len (self.Columns))
|
||||
self._view.setHorizontalHeaderLabels (self.Columns)
|
||||
self._box.addWidget (self._view)
|
||||
self._view.setAlternatingRowColors (True)
|
||||
self._view.setSelectionBehavior (QtWidgets.QAbstractItemView.SelectRows)
|
||||
self._view.verticalHeader ().hide ()
|
||||
self.selection_model = self._view.selectionModel ()
|
||||
self.selection_model.currentChanged.connect (self._current_changed)
|
||||
self._current_row = None
|
||||
# end def __init__
|
||||
|
||||
def _add_read_only_string (self, row, col, text) :
|
||||
item = QtWidgets.QTableWidgetItem (text)
|
||||
flags = item.flags() & ~QT.ItemIsEditable
|
||||
item.setFlags (flags)
|
||||
self._view.setItem (row, col, item)
|
||||
# end def _add_read_only_string
|
||||
|
||||
def _update_read_only_string (self, row, col, text) :
|
||||
item = self._view.item (row, col)
|
||||
if not item :
|
||||
self._add_read_only_string (row, col, text)
|
||||
else :
|
||||
model = self._view.model ()
|
||||
index = model.index (row, col)
|
||||
model.setData (index, text)
|
||||
# end def _update_read_only_string
|
||||
|
||||
def _current_changed (self, new_index, old_index) :
|
||||
row = new_index.row ()
|
||||
if row != self._current_row :
|
||||
self._current_row = row
|
||||
# end def _current_changed
|
||||
|
||||
def save_settings (self, settings) :
|
||||
settings.beginGroup (self.settings_group)
|
||||
settings.setValue ("column-width", self.column_width ())
|
||||
if False and self.selection_model :
|
||||
selection = [ self.model.item_path (i)
|
||||
for i in self.selectionModel ().selectedRows ()
|
||||
]
|
||||
settings.setValue ("selection", selection)
|
||||
settings.endGroup ()
|
||||
# end def save_settings
|
||||
|
||||
def restore_settings (self, settings) :
|
||||
settings.beginGroup (self.settings_group)
|
||||
self.restore_column_width (settings.value ("column-width" ))
|
||||
if False and self.selection_model :
|
||||
self.restore_selection (settings.value ("selection" ))
|
||||
settings.endGroup ()
|
||||
# end def restore_settings
|
||||
|
||||
|
||||
def column_width (self) :
|
||||
result = []
|
||||
for i in range (self._view.columnCount ()) :
|
||||
result.append (self._view.columnWidth (i))
|
||||
return result
|
||||
# end def column_width
|
||||
|
||||
def restore_column_width (self, width) :
|
||||
for i, w in enumerate (width or ()) :
|
||||
self._view.setColumnWidth (i, int (w))
|
||||
# end def restore_column_width
|
||||
|
||||
def restore_selection (self, selected) :
|
||||
sm = self.view.selectionModel ()
|
||||
sm.reset ()
|
||||
model = self.view.model ()
|
||||
if model and selected :
|
||||
iv_index = model.invalid_index
|
||||
for path_to_selected in selected :
|
||||
parent_index = iv_index
|
||||
try :
|
||||
for pp in path_to_selected :
|
||||
index = model.index (pp, 0, parent_index)
|
||||
parent_index = index
|
||||
sm.select (index, sm.__class__.Select | sm.__class__.Rows)
|
||||
except :
|
||||
pass
|
||||
# end def restore_selection
|
||||
|
||||
# end class _With_Table_Widget_
|
||||
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
### create new initial database
|
||||
from schema import User, State, Production_Line, Order,Action, db, orm
|
||||
import datetime
|
||||
|
||||
def get_state () :
|
||||
state = State.get ()
|
||||
if not state :
|
||||
state = State \
|
||||
( imos_export_dir = "?"
|
||||
, pgiq_import_dir = "?"
|
||||
, last_directory_scan = datetime.datetime.fromtimestamp (0)
|
||||
)
|
||||
return state
|
||||
# end def get_state
|
||||
|
||||
if __name__ == "__main__" :
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser ()
|
||||
parser.add_argument ("database", type = str)
|
||||
parser.add_argument ("-u", "--user", type = str)
|
||||
parser.add_argument ("-p", "--password", type = str)
|
||||
parser.add_argument ("--check", action = "store_true")
|
||||
parser.add_argument ("-i", "--imos_dir", type = str)
|
||||
parser.add_argument ("-P", "--pgiq_dir", type = str)
|
||||
parser.add_argument ("-l", "--line", type = str)
|
||||
cmd = parser.parse_args ()
|
||||
|
||||
db.bind (provider = "sqlite", filename = cmd.database, create_db = True)
|
||||
db.generate_mapping (create_tables = True)
|
||||
with orm.db_session :
|
||||
breakpoint ()
|
||||
if cmd.user :
|
||||
u = User.get (username = cmd.user)
|
||||
if not u :
|
||||
u = User (username = cmd.user, password = cmd.password)
|
||||
print (f"Add new user {cmd.user} to the database")
|
||||
else :
|
||||
if cmd.check :
|
||||
print (f"Check password for user {cmd.user}: "
|
||||
f"{u.check_password (cmd.password)}"
|
||||
)
|
||||
else:
|
||||
print (f"Set new password for user {cmd.user}")
|
||||
u.change_password (cmd.password)
|
||||
state = get_state ()
|
||||
if cmd.imos_dir :
|
||||
state.imos_export_dir = cmd.imos_dir
|
||||
if cmd.pgiq_dir :
|
||||
state.pgiq_import_dir = cmd.pgiq_dir
|
||||
print (state)
|
||||
if cmd.line :
|
||||
short, name = cmd.line.split (":")
|
||||
line = Production_Line.get (short = short)
|
||||
if not line :
|
||||
line = Production_Line (short = short, name = name)
|
||||
else :
|
||||
line.name = name
|
||||
print (line)
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
import os
|
||||
from QT.Main_Window import Main_Window, QtWidgets
|
||||
from Order_Display import Order_Display
|
||||
from Login import Login_Dialog
|
||||
from App_State import App_State
|
||||
import designbox_orders_rc
|
||||
import schema
|
||||
import pathlib
|
||||
from lxml import etree
|
||||
|
||||
class Order_Processing (Main_Window) :
|
||||
|
||||
APP_NAME = "Designbox Orders"
|
||||
VERSION = "0.5"
|
||||
APP_ORGANISATION = ("designbox-orders", "glaser-co.at")
|
||||
APP_DIR = os.path.dirname (__file__)
|
||||
|
||||
@classmethod
|
||||
def _load_app_settings (cls, settings) :
|
||||
settings.beginGroup ("TempSettings")
|
||||
result = {"database" : settings.value ("database")}
|
||||
result = {"username" : settings.value ("username")}
|
||||
settings.endGroup ()
|
||||
return result
|
||||
# end def _load_app_settings
|
||||
|
||||
def _setupActions (self, app) :
|
||||
super ()._setupActions (app)
|
||||
self._add_action ("test", "Scan Dir", self.scan_orders_directory)
|
||||
# end def _setupActions
|
||||
|
||||
def _setupGui (self) :
|
||||
self.main_menu = QtWidgets.QMenuBar (self)
|
||||
self.setMenuBar (self.main_menu)
|
||||
file = QtWidgets.QMenu ("& File")
|
||||
self.main_menu.addMenu (file)
|
||||
self.tool_bar_file = self.addToolBar ("File")
|
||||
self.tool_bar_file.setObjectName ("tb_file")
|
||||
for a, l in ( ( self.actions.exit
|
||||
, (file, self.tool_bar_file)
|
||||
)
|
||||
, ( (self.actions.test), (self.tool_bar_file, ))
|
||||
) :
|
||||
for x in l :
|
||||
x.addAction (a)
|
||||
self.setCentralWidget (Order_Display (self))
|
||||
settings = self.settings
|
||||
settings.beginGroup ("TempSettings")
|
||||
user_id = settings.value ("user_id")
|
||||
settings.endGroup ()
|
||||
with schema.orm.db_session :
|
||||
App_State.user_id = schema.User [user_id].id
|
||||
self.scan_orders_directory ()
|
||||
# end def _setupGui
|
||||
|
||||
def _find_orders (self, root_path : pathlib.Path) :
|
||||
result = set ()
|
||||
for path, dirs, files in root_path.walk () :
|
||||
for f in files :
|
||||
if f.endswith (".txt") :
|
||||
xml_name = (path / f).with_suffix (".xml")
|
||||
if xml_name.exists () :
|
||||
result.add (xml_name)
|
||||
for d in dirs :
|
||||
result.intersection_update (self._find_orders (root_path / d))
|
||||
return result
|
||||
# end def _find_orders
|
||||
|
||||
def scan_orders_directory (self) :
|
||||
with schema.orm.db_session :
|
||||
state = schema.State.get ()
|
||||
orders = self._find_orders (pathlib.Path (state.imos_export_dir))
|
||||
with schema.orm.db_session :
|
||||
for o in orders :
|
||||
self._update_order_in_database (o)
|
||||
self.centralWidget ().update_orders ()
|
||||
# end def scan_orders_directory
|
||||
|
||||
def _update_order_in_database (self, xml_file) :
|
||||
basket_no = xml_file.stem
|
||||
if True :
|
||||
order = schema.Order.get (basket_no = basket_no)
|
||||
if not order :
|
||||
xml = etree.parse (xml_file).getroot ()
|
||||
com = xml.xpath ("//TEXT_SHORT") [0].text
|
||||
user,line = xml.xpath ("//RETAILER") [0].text.split ("/")
|
||||
order = schema.Order \
|
||||
( basket_no = basket_no
|
||||
, state = 0
|
||||
, commission = com
|
||||
, imos_user = user
|
||||
, production_line = schema.Production_Line.get (short = line)
|
||||
, active = True
|
||||
)
|
||||
schema.Action \
|
||||
( user = schema.User [App_State.user_id]
|
||||
, date = schema.datetime.now ()
|
||||
, action_kind = 1
|
||||
, action = "Auftrag importiert"
|
||||
, order = order
|
||||
)
|
||||
# end def _update_order_in_database
|
||||
|
||||
def _restore_settings (self) :
|
||||
super ()._restore_settings ()
|
||||
self.centralWidget ().restore_settings (self.settings)
|
||||
# end def _restore_settings
|
||||
|
||||
def save_settings (self) :
|
||||
settings = self.settings
|
||||
super ().save_settings ()
|
||||
self.centralWidget ().save_settings (settings)
|
||||
settings.beginGroup ("TempSettings")
|
||||
settings.setValue ("user_id", App_State.user_id)
|
||||
settings.endGroup ()
|
||||
# end def save_settings
|
||||
|
||||
@classmethod
|
||||
def pre_main_window_action (cls, settings) :
|
||||
settings.beginGroup ("TempSettings")
|
||||
db_file = settings.value ("database")
|
||||
user_id = settings.value ("user_id")
|
||||
settings.endGroup ()
|
||||
schema.db.bind (provider = "sqlite", filename = db_file)
|
||||
schema.db.generate_mapping (create_tables = False)
|
||||
username = ""
|
||||
if user_id :
|
||||
with schema.orm.db_session :
|
||||
username = schema.User [user_id].username
|
||||
if False :
|
||||
login = Login_Dialog (username)
|
||||
if login.exec () == 1 :
|
||||
settings.beginGroup ("TempSettings")
|
||||
settings.setValue ("user_id", login.user_id)
|
||||
settings.endGroup ()
|
||||
return True
|
||||
else :
|
||||
print ("### Login skipped")
|
||||
return True
|
||||
# end def pre_main_window_action
|
||||
|
||||
# end class Order_Processing
|
||||
|
||||
if __name__ == "__main__" :
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser ()
|
||||
parser.add_argument ("-s","--settings-file", type = str)
|
||||
parser.add_argument ("-d", "--database", type = str)
|
||||
cmd = parser.parse_args ()
|
||||
Order_Processing.run (Order_Processing.load_settings (cmd))
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource prefix="icons">
|
||||
<file alias="exit.png">icons/person-from-portal.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
# Resource object code (Python 3)
|
||||
# Created by: object code
|
||||
# Created by: The Resource Compiler for Qt version 6.6.2
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PySide6 import QtCore
|
||||
|
||||
qt_resource_data = b"\
|
||||
\x00\x00\x05\xaf\
|
||||
\x89\
|
||||
PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
|
||||
\x00\x000\x00\x00\x000\x08\x06\x00\x00\x00W\x02\xf9\x87\
|
||||
\x00\x00\x00\x09pHYs\x00\x00\x01b\x00\x00\x01b\
|
||||
\x01_'\xd0S\x00\x00\x00\x19tEXtSof\
|
||||
tware\x00www.inksca\
|
||||
pe.org\x9b\xee<\x1a\x00\x00\x05<ID\
|
||||
ATh\x81\xb5\x9a]\xa8UE\x14\xc7\x7f\xff\xedQ\
|
||||
K\x8bLK\xafD\x18\x91EH\x10!\xe5\x17\x09\xa1\
|
||||
\x99\x9aVRQ\x81\x95=\x18A\x11Q\x06\x11fd\
|
||||
T\x12H\x94\x0fE\x81\x1f\x94=\x18J\x96\xa4\xdd>\
|
||||
(\xd3|\x88\xa8\x88\xec\x9a\xa4\xf6\xa0i\x8a\x96f\x8a\
|
||||
\xe6\xeaa\xf6\xbe\x9c\xb3\xcf\xde{f\xf6\xb9\xfd\xe1p\
|
||||
\xce\x9dY\x9fw\xd6^\xb3f\xcd\x96\x99\x91\x87\xa4\xa1\
|
||||
\xc0$`\x18\xb0\x1f\xd8bf\x7f\xb6\x11v\x08IC\
|
||||
\x80\x85\xc0\x8d\xc0\xa5\xc0\xaf\xc0\xc7\xc0b3;\x12$\
|
||||
#\xef@*\xf4V`@\xd3\xf0I`\x9d\x99\xfd\xd5\
|
||||
\x07vgz\x86\x01[\x80+\x0a\xa6{\x80\x89fv\
|
||||
\xc8'')\x18\x9bL\xab\xf1\x00\x03\x81)\x92\x14k\
|
||||
h\x05\x9e\xa1\xd8x\xd2\xf1\x85!BZ\x1c\x904\x1a\
|
||||
\x18QB{\x010:\xd4\xba\x00\xdc\xd6\xe1<\xd0\xbe\
|
||||
\x02\xd7x\xe8\xaf\x0e\x11\x1a\x88\xb2\x7fT\x86\xae\x10!\
|
||||
\xbd\x0eH\xea\x02\xce\xf3\xd0\x0f\x9142Dp\x00\xf6\
|
||||
{\xe6\x7f\x0f\x11\xd2\xbc\x02\x97\x07*\xee\xab0Z\xd7\
|
||||
\xe1<\x90:\x90>\x9c\x97\x04*\x1e\xd5G\x0f\xf3s\
|
||||
\xb8lS\x84\x1e`q\x88\x90l\x05\x86\x02g\x05*\
|
||||
>\x1b\xb80\x90\xb6\x14i\x8a\x1c\x07,\x05~\x04\x8e\
|
||||
\xa7\xdfK\x81q!)\x14\xa0\x91~_\x14\xa9\xbf\x0b\
|
||||
8\x90\x1f\x94\xd4\x0f\xb7)\xcd\x06&\xa6t\xe7\x03\x87\
|
||||
\x80\x9f\x81/\x81\x0f\x81o\xcc\xecL\xbaY=\x1e\xa9\
|
||||
\xbbU\xa7\x99!i\x1a0*\x82o\x97\x99u\xe7\x8c\
|
||||
\x9f\x05\xbc\x08\x8c\x09\xe0\xdf\x07|\x00\xbc\x0f|jf\
|
||||
'#t\xb7 \x0b\xa1a\x91|\xc3\xb3\x1f\x92\x1a\x92\
|
||||
^\x01\xd6\x13f<\xc0H`>\xb0\x01\xd8-\xe9Y\
|
||||
I\xbe\xb4Z\x88DR\x7f\xe0\x9cH\xbe\xc1\x92\x06J\
|
||||
\x1a\x08\xac\x05\x1e\xad\xa3<E\x17\xb0\x08\xe8\x91tw\
|
||||
,s\x82\x8b\xd1:\x18\x0e\xbc\x07\xcc\xaa\xc9\x9f\xc7y\
|
||||
\xc0jI\xaf\xc7d\xb9N\x1cX\x06\xdc\x5c\x93\xb7\x0a\
|
||||
\x0f\x02KB\x89\x13\xe2\xc3\x07\x5c]4\xbbb\xbe\x07\
|
||||
\x98\x8b\x0b\x8f;k\xc8_ \xe9\xde\x10\xc2\x04\x97\xd7\
|
||||
cQ\xb5\x0ft\x03c\xcd\xecm3\xdb\x0f\xdcQC\
|
||||
>\xc0\x12I\xe7\xfa\x88\x12`P\x0d\xe1\x7f\x94\x8cw\
|
||||
\x03\xb7\x98\xd91\x00I\x83\x80\x195\xe4\x83[\xbd'\
|
||||
|Du\x1d8\x88\xcb\xe1\xcdX\x8f3\xfe\x9f\xa6\xb1\
|
||||
\x99\xc0\xe0\x1a\xf23<,\xa92B\x12\xc2K\x88<\
|
||||
\xde\x05n\x02\x16\x00\xd3\xcd,o<\xd4\x0f\x9f\x0cC\
|
||||
\x81\x87\xaa\x08\x1a@\xbf\x9a\xc2\xfb\x99\xd9&`S\xd1\
|
||||
dd\xf8\x18\xf0=\xc5\xe7\x8d\x97$%\xc0J3k\
|
||||
\x0b\xdd\x84\xfa\x0e4<\xf31\xe1\xf3\x15\xf0T\xc9\x5c\
|
||||
\x7f\xe0e\xe0\x80$K?{%-\x914\xa0\x11`\
|
||||
H\x19|\x8e\xdf\x1e!k\xa5\x99m\x94\xb4\x15\x98\x10\
|
||||
@?\x12x\x12\xb0NV\xa0\x94/\x0d\x9f\x99\x81r\
|
||||
\x8e\x03k\xd2\xdf\xf3\x80\xa3\x116\xcc-\xeaJ\xf4\x05\
|
||||
&\x10\x1e>k\xb3v\x8d\x99\xed\xc09\x1e\xdc\x83J\
|
||||
\x80\x7f\xa3\xcds\xa8\xe2\x8b)\xcdW4\xffaf\x9b\
|
||||
\x81kq\xcf\x85\x0f\xab\x12\xe0t\x84\xb2fT9p\
|
||||
,P\xc6\x1e\xe0\xf3\xfc`\xba\x12\xd7\x03Sq\x0e\xee\
|
||||
\xc4\x85Z\x86\xbd\xb8ziQ\xc3cH\x15\xaa\xf8\xb6\
|
||||
\xe1R\xa3\xaf\xaa\x5cefg\x8a&\xcc\xb5\x0c?I\
|
||||
?\xa5\xf8_B\xc8\xcc\xf6\xe0N\x5c>\xcc\x914\xb1\
|
||||
\xa6~\xc09p\xa2&o\xcb\xae\x9b\x9e\xcc\xeej\x1a\
|
||||
z\x04\x7fog\x0c\xb0Y\xd2\x1b\x92j\x95\xf5\x09\xad\
|
||||
\xb1\x15\x83|\xd90\x07xU\xd2p\x003\xfb\x0d\xd7\
|
||||
g\xfd\xc1#G\xb8\xe3\xe5vI\xf7\xc4\x1a\xd1\x89\x03\
|
||||
y\xbe\xc7pe\xf6\xaa\xf4\x98\x9a=\x8cc\x81\xa7i\
|
||||
w8\x8f\x11\xc0;\x926H\xf2u\x08{\xd1'+\
|
||||
i\x02\xae\xc7\x030\x0dX\x93\xd5\xf2fv\xca\xcc\
|
||||
^\x00\xae\xc2\xf5\xfe}\x98\x01t\xa7-\x1a/\x84k\
|
||||
eO\x0e\xa0\x1b\x9f\x1a\x17\xd4t\xc5\xa5\xbeyf\xd6\
|
||||
\x92\xcf\xd30Y\x8a\xbf\xb9\xfb\x80\x99-\xf7)I\x80\
|
||||
\xc3\x01\xc6\x8c\x07\xee#\xdcx\x80\xcb\x80\xeb\xf2\x83f\
|
||||
\xb6\x1a\xb8\x12x\x13\x97j\xcb05DI\xa8\x03\xd3\
|
||||
B\x84\xe5p\x14x\xabh\xc2\xcc\x0e\x9b\xd9|\xdcf\
|
||||
\xf5K\x09\x7f\xd09%1\xb3S\x84\xef\x9c1x\xcd\
|
||||
w\xaf\x96\x86\xd7\xf6\x92\xe92\xc7Z\x90\x15s\xbeF\
|
||||
\xea\xc6\x10aM\xd8\x0a<\xef#J\x1bc7\x94L\
|
||||
w\x97\x8c\xb7 s`\x9f\x87n\x1b\xae&\xa9\xa2;\
|
||||
\x0d\xec\xc0\xdd}M)8^\x16a\x12\xc5m\x9dc\
|
||||
\xc0\xe6\x00\xfe\xde\xc3\xcc^\x0f\x9d\x01_\xa7\x1fp%\
|
||||
\xf0\xc1\x10\x05\x1e\x94\x1d9?\x0bm\xf86\x87Ph\
|
||||
I\xf1w\x1f\x19\x0f0\xbdd\xfc\xa3P\x01\x09\xf4V\
|
||||
~\xbb\x03yv\x85\x0a\xaf\x82\xa4\x8bq\xe9\xb4\x08\xc1\
|
||||
\xcf\x5c\xf3\x89\xac\xec\xba'\x8f\xdd\xa1\xc2=(;r\
|
||||
\xfedf\xc1:z\x1dH\xdb\x80\xbe\xeb\xfd#f\xe6\
|
||||
{^B\xd1q\xf8@\xfb=\xf1\xb7\x1e\xfa\xefb\x84\
|
||||
{\xd0\xb6K\xa7\x88J\xd9-\x0e\x98\xd9N\xca\xefo\
|
||||
\x0f\x12\xb8\xb9\x04\xa2\xe8\xb4v\x94\xc0\xf4\x99\xa1\xa8+\
|
||||
\xf1\x05\xee\xe5\x8ef\x9c\xc0\xddeU\xd5.\xb1XQ\
|
||||
0\xb6,\xf6\xbe\xac\xedm\x15\x80\xf4t4\x09W\xdf\
|
||||
g\xaf\xdb\x04\xbd\xfe\x12\xacXj\xe0\xee\x82\xef\xc7\xad\
|
||||
\xc6r`\xa1\x99E5\x19\xfe\x036\xda\x8b\xa9m\xbd\
|
||||
\x82T\x00\x00\x00\x00IEND\xaeB`\x82\
|
||||
"
|
||||
|
||||
qt_resource_name = b"\
|
||||
\x00\x05\
|
||||
\x00o\xa6S\
|
||||
\x00i\
|
||||
\x00c\x00o\x00n\x00s\
|
||||
\x00\x08\
|
||||
\x0f\x07Z\xc7\
|
||||
\x00e\
|
||||
\x00x\x00i\x00t\x00.\x00p\x00n\x00g\
|
||||
"
|
||||
|
||||
qt_resource_struct = b"\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
|
||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||
\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||
\x00\x00\x01\x8e\xf0\xcd\xec\xfe\
|
||||
"
|
||||
|
||||
def qInitResources():
|
||||
QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
def qCleanupResources():
|
||||
QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
|
||||
|
||||
qInitResources()
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
|
|
@ -0,0 +1,122 @@
|
|||
from pony import orm
|
||||
import datetime
|
||||
from hashlib import sha256
|
||||
from datetime import datetime
|
||||
|
||||
db = orm.Database ()
|
||||
key = "b9281aea-4a9e-4721-b932-5b5ffbc66cfe"
|
||||
|
||||
class User (db.Entity) :
|
||||
|
||||
username = orm.Required (str, unique = True)
|
||||
password = orm.Required (str)
|
||||
active = orm.Optional (bool)
|
||||
last_logedin = orm.Optional (datetime)
|
||||
created = orm.Optional (datetime)
|
||||
actions = orm.Set ("Action")
|
||||
orders = orm.Set ("Order")
|
||||
|
||||
def __init__ (self, username, password, active = True) :
|
||||
pwd = f"{key}:{password}"
|
||||
password = sha256 (pwd.encode ("utf-8")).hexdigest ()
|
||||
super ().__init__ \
|
||||
( username = username
|
||||
, password = password
|
||||
, active = active
|
||||
, created = datetime.now ()
|
||||
)
|
||||
# end def __init__
|
||||
|
||||
def check_password (self, password) :
|
||||
pwd = f"{key}:{password}"
|
||||
password = sha256 (pwd.encode ("utf-8")).hexdigest ()
|
||||
return self.password == password
|
||||
# end def check_password
|
||||
|
||||
def change_password (self, password) :
|
||||
pwd = f"{key}:{password}"
|
||||
self.password = sha256 (pwd.encode ("utf-8")).hexdigest ()
|
||||
# end def change_password
|
||||
|
||||
# end class User
|
||||
|
||||
class Production_Line (db.Entity) :
|
||||
|
||||
short = orm.Required (str)
|
||||
name = orm.Required (str)
|
||||
orders = orm.Set ("Order")
|
||||
|
||||
def __str__ (self) :
|
||||
return f"{self.name} ({self.short})"
|
||||
# end def __str__
|
||||
|
||||
# end class Production_Line
|
||||
|
||||
class Order (db.Entity) :
|
||||
basket_no = orm.Required (str)
|
||||
state = orm.Required (int)
|
||||
commission = orm.Optional (str)
|
||||
imos_user = orm.Required (str)
|
||||
production_line = orm.Required (Production_Line)
|
||||
user = orm.Optional (User)
|
||||
active = orm.Optional (bool)
|
||||
actions = orm.Set ("Action")
|
||||
order_lines = orm.Set ("Order_Line")
|
||||
# end class Order
|
||||
|
||||
class Action (db.Entity) :
|
||||
user = orm.Required (User)
|
||||
date = orm.Required (datetime)
|
||||
action_kind = orm.Required (int)
|
||||
action = orm.Optional (str)
|
||||
order = orm.Optional (Order)
|
||||
# end class Action
|
||||
|
||||
class Odoo_Article (db.Entity) :
|
||||
name = orm.Required (str)
|
||||
default_text = orm.Optional (str)
|
||||
default_price = orm.Optional (float)
|
||||
order_lines = orm.Set ("Order_Line")
|
||||
# end class Odoo_Article
|
||||
|
||||
class Order_Line (db.Entity) :
|
||||
order = orm.Required (Order)
|
||||
text = orm.Required (str)
|
||||
price = orm.Required (float)
|
||||
odoo_article = orm.Required (Odoo_Article)
|
||||
# end class Order_Line
|
||||
|
||||
class State (db.Entity) :
|
||||
|
||||
imos_export_dir = orm.Required (str)
|
||||
imos_order_dir = orm.Required (str)
|
||||
sim_archive = orm.Required (str)
|
||||
pgiq_import_dir = orm.Required (str)
|
||||
last_directory_scan = orm.Required (datetime)
|
||||
|
||||
def __str__ (self) :
|
||||
return f"""
|
||||
IMOS dir {self.imos_export_dir}
|
||||
PGIQ dir {self.pgiq_import_dir}
|
||||
Last scan {self.last_directory_scan}
|
||||
""".strip ()
|
||||
# end def __str__
|
||||
|
||||
# end class State
|
||||
|
||||
if __name__ == "__main__" :
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser ()
|
||||
parser.add_argument ("database", type = str)
|
||||
parser.add_argument ("-d", "--sql-debug", action = "store_true")
|
||||
cmd = parser.parse_args ()
|
||||
orm.set_sql_debug (cmd.sql_debug)
|
||||
db.bind (provider = "sqlite", filename = cmd.database, create_db = True)
|
||||
db.generate_mapping (create_tables = True)
|
||||
if False :
|
||||
with orm.db_session :
|
||||
u = User (username = "glueckm", password = "123")
|
||||
if True :
|
||||
with orm.db_session :
|
||||
u = User.get (username = "glueckm")
|
||||
print (u, u.check_password ("123"))
|
||||
Loading…
Reference in New Issue