order-processing/Order_Watch.py

145 lines
5.5 KiB
Python

from pathlib import Path
from lxml import etree
from App_State import App_State, Attr_Dict
from filesystem_watcher import \
_Logger_, WindowsApiObserverExcpetionHandler, \
WindowsApiEmitterExceptionHandling, Directory_Handler
import time
import json
import datetime
class Order_Handler (Directory_Handler) :
def __init__ (self, path, client, config) :
super ().__init__ (path)
self.client = client
mqr = config.mqtt ["topic-root"]
baskets = f"{mqr}/baskets"
self.mqtt = Attr_Dict \
( basket_topic = f"{baskets}/{{basket_no}}"
, basket_state = f"{baskets}/{{basket_no}}/state"
, basket_user = f"{baskets}/{{basket_no}}/user"
, basket_changed = f"{baskets}/{{basket_no}}/changed"
, baskets = baskets
)
# end def __init__
def on_any_event (self, event) :
if event.event_type == 'created' :
file = Path (event.src_path)
if file.suffix == ".txt" :
xml = file.with_suffix (".xml")
if xml.exists () :
self.new_order (xml)
if file.suffix == ".xml" :
txt = file.with_suffix (".txt")
if txt.exists () :
self.new_order (file)
elif event.event_type == 'deleted' :
file = Path (event.src_path)
if file.suffix == ".xml" :
basket_no = file.stem
for t in self.mqtt.values () :
self.client.publish \
( t.format (basket_no = basket_no)
, payload = None, retain = False
)
self.L.info ("Order removed %s", basket_no)
super ().on_any_event (event)
# end def on_any_event
def new_order (self, xml_file : Path) :
try :
self.L.info ("New basket %s", xml_file.name)
xml = etree.parse (xml_file).getroot ()
com = xml.xpath ("//TEXT_SHORT") [0].text
user, line = xml.xpath ("//INFO8") [0].text.split ("/")
basket_no = xml_file.stem
self.client.publish \
( self.mqtt.basket_state.format (basket_no = basket_no)
, payload = "new", retain = True
)
self.client.publish \
( self.mqtt.basket_changed.format (basket_no = basket_no)
, payload = App_State.snow ("import"), retain = True
)
basket = dict \
(user = user, line = line, commission = com)
basket ["positions"] = self._scan_order_pos (xml)
self.client.publish \
( self.mqtt.basket_topic.format (basket_no = basket_no)
, payload = json.dumps (basket), retain = True
)
self.L.info ("Created new basket %s", basket_no)
except Exception as e :
self.L.error (e, exc_info = True)
# end def new_order
def _scan_order_pos (self, xml) :
result = []
bl = xml.xpath ("//BuilderList") [0]
for a in bl.getchildren () :
art_name = a.xpath ("Pname") [0].text.strip ()
count = int (a.xpath ("Count") [0].text)
pos = a.get ("LineNo")
text = a.xpath ("ARTICLE_TEXT_INFO1" ) [0].text.strip ()
price = float (a.xpath ("ARTICLE_PRICE_INFO1") [0].text)
result.append \
( dict ( art_name = art_name
, count = count
, pos = pos
, text = text
, price = price
)
)
return result
# end def _scan_order_pos
# end class Order_Handler
class Order_Watch (App_State) :
order_incomming_dir = r"n:\glueck\watch-me\inbox"
def __init__ (self, config_file) :
self.load_config (config_file)
self.client = self.connect_to_mqtt ()
# end def __init__
def _start_watchdog (self) :
handler = Order_Handler \
(self.order_incomming_dir, self.client, self.config)
return WindowsApiObserverExcpetionHandler.Start_Directory_Watcher \
(handler)
# end def _start_watchdog
def run (self) :
observer = None
try:
observer = self._start_watchdog ()
while True:
time.sleep (1)
if WindowsApiEmitterExceptionHandling.Exception :
App_State.L.exception \
(str (WindowsApiEmitterExceptionHandling.Exception))
WindowsApiEmitterExceptionHandling.Exception = None
if observer :
observer.stop ()
observer = self._start_watchdog ()
finally :
if observer :
observer.stop ()
observer.join ()
# end def run
# end class Order_Watch
if __name__ == "__main__" :
parser = Order_Watch.Add_Logging_Attributes ()
parser.add_argument ("config_file", type = str)
cmd = parser.parse_args ()
_Logger_.L = Order_Watch.Setup_Logging (cmd)
ow = Order_Watch (cmd.config_file)
ow.run ()