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