Esempio n. 1
0
def main():
    def progressHandler(prestaProgressEvent):
        if prestaProgressEvent.is_finished:
            print('%s' % prestaProgressEvent.msg)
        else:
            print('%i/%i - %s' %
                  (prestaProgressEvent.current_step,
                   prestaProgressEvent.max_step, prestaProgressEvent.msg))

# A CachedPrestaHelper is a PrestaHelper with cache capabilities

    cachedphelper = CachedPrestaHelper(config.presta_api_url,
                                       config.presta_api_key,
                                       debug=False,
                                       progressCallback=progressHandler)
    # Force loading cache
    #   cachedphelper.load_from_webshop()

    #tester = CachedPrestaHelperTest( cachedphelper )
    #tester.test_cache()
    print('******************************************************************')
    print('*  Cache statistics                                              *')
    print('******************************************************************')
    print('Type of Helper is %s' % type(cachedphelper))
    print('#Carriers = %s' % len(cachedphelper.carriers))
    print('#OrderStates = %s' % len(cachedphelper.order_states))
    print('#Products = %i' % len(cachedphelper.products))
    print('#suppliers = %i' % len(cachedphelper.suppliers))
    print('#categories = %i' % len(cachedphelper.categories))
    print('#stock availables = %i' % len(cachedphelper.stock_availables))

    #print('mise à jour des qty' )
    #cachedphelper.stock_availables.update_quantities()
    #print( 'Voila, c est fait' )

    print('******************************************************************')
    print('*  Derniers Messages client                                      *')
    print('******************************************************************')
    """ affiche les x derniers messages clients """
    id = cachedphelper.get_lastcustomermessage_id()
    print('last message id: %s' % id)
    custmsgs = cachedphelper.get_lastcustomermessages(id, 10)
    for custmsg in reversed(custmsgs):  # CustomerMessageData
        print('--- id: %s---------------' % custmsg.id)
        print('   date_add: %s' % custmsg.date_add)
        print('   read    : %s' % custmsg.read)
        print('   Employee: %s' % custmsg.id_employee)
        print('   id_customer_thread: %s' % custmsg.id_customer_thread)
        print(custmsg.message)
        print('')
    # Ensure cache file to be saved (and will be automatically reloaded)
    #cachedphelper.save_cache_file()

    # read char on keyboard
    print('Press a key to continue:')
    char = sys.stdin.read(1)
    return 0
Esempio n. 2
0
	def __init__( self ):
		self.config = Config()
		self.h = CachedPrestaHelper( self.config.presta_api_url, self.config.presta_api_key, debug= False )
		self.output = PrestaOut()
		self.state  = AppState.WAIT_ORDER
		# Loaded order
		self.order    = None
		self.joined_order = [] # other order joined to the shipping
		self.customer = None
		self.carrier  = ''
		self.shipping_number = ''
		self.output.writeln( "Application initialized" )
Esempio n. 3
0
def main():
	def progressHandler( prestaProgressEvent ):
		if prestaProgressEvent.is_finished:
			print( '%s' %prestaProgressEvent.msg )
		else:
			print( '%i/%i - %s' % ( prestaProgressEvent.current_step, prestaProgressEvent.max_step, prestaProgressEvent.msg ) )
    
    # A CachedPrestaHelper is a PrestaHelper with cache capabilities	
	cachedphelper = CachedPrestaHelper( config.presta_api_url, config.presta_api_key, debug = False, progressCallback = progressHandler )
	# Force loading cache
	#   cachedphelper.load_from_webshop()
	
	#tester = CachedPrestaHelperTest( cachedphelper )
	#tester.test_cache()
	print( '******************************************************************' )
	print( '*  Cache statistics                                              *' )
	print( '******************************************************************' )
	print( 'Type of Helper is %s' % type(cachedphelper) )
	print( '#Carriers = %s' % len(cachedphelper.carriers) )
	print( '#OrderStates = %s' % len( cachedphelper.order_states ) )
	print( '#Products = %i' % len( cachedphelper.products ) )
	print( '#suppliers = %i' % len( cachedphelper.suppliers ) )
	print( '#categories = %i' % len( cachedphelper.categories ) )
	print( '#stock availables = %i' % len( cachedphelper.stock_availables ) )
			
	#print('mise à jour des qty' )
	#cachedphelper.stock_availables.update_quantities()
	#print( 'Voila, c est fait' )
		
	print( '******************************************************************' )
	print( '*  Derniers Messages client                                      *' )
	print( '******************************************************************' )
		
	""" affiche les x derniers messages clients """
	id = cachedphelper.get_lastcustomermessage_id()
	print( 'last message id: %s' % id )
	custmsgs = cachedphelper.get_lastcustomermessages( id, 10 )
	for custmsg in reversed(custmsgs): # CustomerMessageData
		print( '--- id: %s---------------' % custmsg.id )
		print( '   date_add: %s' % custmsg.date_add )
		print( '   read    : %s' % custmsg.read )
		print( '   Employee: %s' % custmsg.id_employee )
		print( '   id_customer_thread: %s' % custmsg.id_customer_thread )
		print( custmsg.message )
		print( '' )		
	# Ensure cache file to be saved (and will be automatically reloaded)
	#cachedphelper.save_cache_file()
	
	# read char on keyboard
        print( 'Press a key to continue:' ) 
	char = sys.stdin.read(1) 
	return 0
Esempio n. 4
0
def main():
	global cachedHelper
	""" Simply create the global reference cachedHelper. Useful for 
	interfactive debugging """
	# just create the needed object
	logging.info( 'create cachedHelper object' )
	cachedHelper = CachedPrestaHelper( config.presta_api_url, config.presta_api_key, debug = False )
	
	value = raw_input( 'Rafraichir le cache (y/n)' )
	if value == 'y':
		logging.info( 'Force cache refreshing from WebShop' )
		cachedHelper.load_from_webshop()
		logging.info( 'Saving cache file' )
		cachedHelper.save_cache_file()
		logging.info( 'file saved' )
	else:
		logging.info( 'Data not refreshed from the WebShop' )
Esempio n. 5
0
	def __init__( self, screen ):
		self.screen = screen 
		(self.height, self.width) = screen.getmaxyx()
		self.subwin = [] # Subwin list
		self.create_subwin()

		# Create a SysLog handler
		self.logger = logging.getLogger()
		self.logger.setLevel( logging.DEBUG )
		# Follow the log with
		#    tail -f /var/log/syslog 
		# formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s')
		#    also mention the python filename in the log
		formatter = logging.Formatter( os.path.basename(__file__)+' :: %(levelname)s :: %(message)s')
		sys_handler = SysLogHandler( address = '/dev/log')
		sys_handler.setLevel( LOGGING_LEVEL )
		sys_handler.setFormatter( formatter )
		self.logger.addHandler( sys_handler )

		self.logger.info( 'Starting app' )
		self.config = Config()
		self.cachedphelper  = CachedPrestaHelper( self.config.presta_api_url, self.config.presta_api_key, debug = False ) #, progressCallback = progressHandler )
		# initialize global variables
		self.initialize_globals()
Esempio n. 6
0
def main():
    def progressHandler(prestaProgressEvent):
        if prestaProgressEvent.is_finished:
            print('%s' % prestaProgressEvent.msg)
        else:
            print('%i/%i - %s' %
                  (prestaProgressEvent.current_step,
                   prestaProgressEvent.max_step, prestaProgressEvent.msg))

    def initialize_globals():
        """ Initialize the global var @ startup or @ reload """
        global ID_SUPPLIER_PARAMS
        _item = cachedphelper.suppliers.supplier_from_name("PARAMS")
        #for _item in cachedphelper.suppliers:
        #	print( '%i - %s' % (_item.id,_item.name) )
        if _item != None:
            ID_SUPPLIER_PARAMS = _item.id
            print('Catched PARAMS supplier :-). ID: %i' % ID_SUPPLIER_PARAMS)

# A CachedPrestaHelper is a PrestaHelper with cache capabilities

    cachedphelper = CachedPrestaHelper(config.presta_api_url,
                                       config.presta_api_key,
                                       debug=False,
                                       progressCallback=progressHandler)
    # Force loading cache
    #   cachedphelper.load_from_webshop()

    #tester = CachedPrestaHelperTest( cachedphelper )
    #tester.test_cache()
    print('******************************************************************')
    print('*  Cache statistics                                              *')
    print('******************************************************************')
    print('Type of Helper is %s' % type(cachedphelper))
    print('#Carriers = %s' % len(cachedphelper.carriers))
    print('#OrderStates = %s' % len(cachedphelper.order_states))
    print('#Products = %i' % len(cachedphelper.products))
    print('#suppliers = %i' % len(cachedphelper.suppliers))
    print('#categories = %i' % len(cachedphelper.categories))
    print('#stock availables = %i' % len(cachedphelper.stock_availables))
    print('#product suppliers available = %i' %
          len(cachedphelper.product_suppliers))
    print('******************************************************************')
    print('')
    initialize_globals()

    #print('mise à jour des qty' )
    #cachedphelper.stock_availables.update_quantities()
    #print( 'Voila, c est fait' )

    value = ''
    while value != '+q':
        try:
            value = raw_input('What to do: ')

            # -- COMMANDS ------------------------------------------
            # +q, +s, +r
            g = re_command.match(value)
            if g:
                cmd = g.groups()[0]
                if cmd == 'q':
                    return
                if cmd == 's':
                    print('Saving cache...')
                    cachedphelper.save_cache_file()
                if cmd == 'r':
                    print('Contacting WebShop and reloading...')
                    cachedphelper.load_from_webshop()
                    initialize_globals()  # reinit global variables
                if cmd == 'e':
                    # export the inventory list
                    lst = build_inventory_list(cachedphelper)
                    sorted_lst = sorted(lst, key=lambda cargo: cargo.reference)
                    root = export_to_xmltree(sorted_lst)
                    tree = etree.ElementTree(root)

                    root = Tk()
                    root.filename = tkFileDialog.asksaveasfilename(
                        title="Exporter vers fichier XML",
                        filetypes=(("xml", "*.xml"), ("all files", "*.*")))
                    if (root.filename == u''):
                        print('User abort!')
                        root.destroy()
                        continue
                    tree.write(root.filename)
                    root.destroy()
                    print('exported to %s' % root.filename)

                if cmd == 'h':
                    help()

                # restart loop
                continue

            # -- SEARCH -------------------------------------------
            # GSM,  /-LIPO,
            #g = re_search_text.match( value )
            #if g:
            #	# Text to search = groups()[0] if "demo" or groups()[1] if "/-lipo"
            #	txt = g.groups()[0] if g.groups()[0] else g.groups()[1]
            #	list_products( cachedphelper, key = txt )
            #	continue

        except Exception as err:
            print('[ERROR] %s' % err)
            traceback.print_exc()
    # eof While

    return
Esempio n. 7
0
def main():
    cachedHelper = CachedPrestaHelper(config.presta_api_url,
                                      config.presta_api_key,
                                      debug=False)
    lcd = EuropeLcdMatrix(config.lcd_device)
    lcd.create_european_charset()

    lcd.clear_screen()
    lcd.autoscroll(False)
    lcd.activate_lcd(True)
    lcd.write_european_pos(1, 1, u'LcdOrderTrack')
    lcd.write_european_pos(2, 1, u'     starting...')

    # default values for variable
    last_order_id = -1
    last_order_data = None
    bNewPayment = False
    paid_count = 0
    bankwire_count = 0

    # Locate the ID_Payment for "Paiement par carte sur place"
    PAY_AT_MCH = None
    for order_state in cachedHelper.order_states:
        if cachedHelper.order_states.name_from_id(
                order_state.id).upper().find(u'CARTE SUR PLACE') >= 0:
            PAY_AT_MCH = order_state.id

    try:
        # Force initial update
        last_update_time = time.time() - UPDATE_DELAY
        while True:
            if math.floor(time.time() - last_update_time) >= UPDATE_DELAY:
                lcd.clear_screen()
                lcd.write_european(u'Updating...')

                # Identifying the last Order!
                last_order_id = cachedHelper.get_lastorder_id()
                last_orders_data = cachedHelper.get_last_orders(last_order_id,
                                                                count=1)
                # bOpenOrder = cachedHelper.order_states.is_open_order( last_orders_data[0].current_state )
                #   Exclude the REAPPROVISIONNEMENT state from light
                #   the LCD. Payment is effectively DONE but
                #   no work/shipping has to be prepared
                # New order with "Payment sur place" will deliver money shortly
                #   so it is also like a "new payment" --> switch on the light
                bNewPayment = (cachedHelper.order_states.is_new_order(
                    last_orders_data[0].current_state) or
                               (cachedHelper.order_states.name_from_id(
                                   last_orders_data[0].current_state).upper().
                                find(u'CARTE SUR PLACE') >= 0)) and (
                                    last_orders_data[0].current_state !=
                                    OrderStateList.ORDER_STATE_REPLENISH)

                # Activate LCD when receiving a new payment
                setLcdColor(lcd, cachedHelper, last_orders_data[0])
                lcd.activate_lcd(bNewPayment)
                paid_count = len(
                    cachedHelper.get_order_ids(
                        cachedHelper.order_states.ORDER_STATE_PAID))
                bankwire_count = len(
                    cachedHelper.get_order_ids(
                        cachedHelper.order_states.ORDER_STATE_WAIT_BANKWIRE))
                # Also add the "Paiement par carte sur place" in Bankwire count
                if PAY_AT_MCH:
                    bankwire_count += len(
                        cachedHelper.get_order_ids(PAY_AT_MCH))

                last_update_time = time.time()
            else:
                sInfo = u'upd in %i sec' % int(
                    UPDATE_DELAY - math.floor(time.time() - last_update_time))
                sInfo = (sInfo[:16]).ljust(16)
                lcd.write_european_pos(2, 1, sInfo)
                time.sleep(2)

            # Show Count of payments
            sPayInfo = u'Pay %s | Vir %s' % (paid_count, bankwire_count)
            sPayInfo = sPayInfo.center(16)
            lcd.write_european_pos(1, 1, sPayInfo)

            # Show information about last Order
            showOrderInfo(lcd, cachedHelper, last_orders_data[0])

    except Exception, e:
        lcd.clear_screen()
        lcd.write_european_pos('KABOUM!!')
        lcd.write_european_pos(2, 1, u'Restart in 5 Min')
        logging.exception(e)
        time.sleep(5 * 60)
        os.system('sudo reboot')
        return 0
Esempio n. 8
0
def main():
	def progressHandler( prestaProgressEvent ):
		if prestaProgressEvent.is_finished:
			print( '%s' %prestaProgressEvent.msg )
		else:
			print( '%i/%i - %s' % ( prestaProgressEvent.current_step, prestaProgressEvent.max_step, prestaProgressEvent.msg ) )

	def initialize_globals():
		""" Initialize the global var @ startup or @ reload """
		global ID_SUPPLIER_PARAMS
		_item = cachedphelper.suppliers.supplier_from_name( "PARAMS" )
		#for _item in cachedphelper.suppliers:
		#	print( '%i - %s' % (_item.id,_item.name) )
		if _item != None:
			ID_SUPPLIER_PARAMS = _item.id
			print( 'Catched PARAMS supplier :-). ID: %i' % ID_SUPPLIER_PARAMS )	
    
    # A CachedPrestaHelper is a PrestaHelper with cache capabilities	
	cachedphelper = CachedPrestaHelper( config.presta_api_url, config.presta_api_key, debug = False, progressCallback = progressHandler )
	# Force loading cache
	#   cachedphelper.load_from_webshop()
	
	#tester = CachedPrestaHelperTest( cachedphelper )
	#tester.test_cache()
	print( '******************************************************************' )
	print( '*  Cache statistics                                              *' )
	print( '******************************************************************' )
	print( 'Type of Helper is %s' % type(cachedphelper) )
	print( '#Carriers = %s' % len(cachedphelper.carriers) )
	print( '#OrderStates = %s' % len( cachedphelper.order_states ) )
	print( '#Products = %i' % len( cachedphelper.products ) )
	print( '#suppliers = %i' % len( cachedphelper.suppliers ) )
	print( '#categories = %i' % len( cachedphelper.categories ) )
	print( '#stock availables = %i' % len( cachedphelper.stock_availables ) )
	print( '#product suppliers available = %i' % len( cachedphelper.product_suppliers ) )
	print( '******************************************************************' )
	print( '' )		
	initialize_globals()

	#print('mise à jour des qty' )
	#cachedphelper.stock_availables.update_quantities()
	#print( 'Voila, c est fait' )
	
	value = ''
	while value != '+q':
		print( '='*40 )
		print( '  +r : reload cache           | +s          : save cache' )
		print( '  +12: ean12 to ean13         | +e          : create ean13' )
		print( '  id : id product to print    | partial_code: to search' )
		print( '  +ol: On demand label (Large)| +al         : address label' )
		print( '  +os: On demand label (Short)| +openl      : open for... label' )
		print( '  +ok: On demand label (King) | +w          : Warranty')
		print( '  +q : quit ' )
		print( '='*40 )
		print( '' )
		value = raw_input( 'What to do: ' )
		
		if value == '+q':
			pass
		elif value == '+r':
			print( 'Contacting WebShop and reloading...' )
			cachedphelper.load_from_webshop()
			initialize_globals() # reinit global variables	
		elif value == '+s':
			print( 'Saving cache...' )
			cachedphelper.save_cache_file()
		elif value == '+12':
			ean12_to_ean13()
		elif value == '+e':
			product_id_to_ean13()
		elif value == '+ol': #On_demand Large label
			ondemand_label_large()
		elif value == '+os': #On_demand Short label
			ondemand_label_short()
		elif value == '+ok': #On_demand King Size Label
			line1 = raw_input( 'Line 1: ' )
			if line1 == '+q' or line1 == '':
				continue
			line2 = raw_input( 'Line 2: ' )
			
			print_ondemand_label_kingsize( line1, line2 )
		elif value == '+al': # adress Label
			value = raw_input( 'How many labels or +q: ' )
			if value == '+q' or value=='0':
				continue
			if value == '':
				value = '1'
			qty = int( value )
			if qty > 25:
				qty = 25
				print( 'Max 25 labels allowed! Value sharped to 25.' )
				
			print_ondemand_label_large( 'MC Hobby SPRL',
				[ unicode( config.company_address[0]  ),
				unicode( config.company_address[1]  ),
				unicode( config.company_address[2]  ),
				unicode( u'TVA/VAT: %s' % config.company_vat   ), 
				unicode( u'Phone  : %s' % config.company_phone ),
				unicode( u'Web    : %s' % config.company_url   )
				], qty )

		elif value == '+openl': 
			value = raw_input( 'How many labels or +q: ' )
			if value == '+q' or value=='0':
				continue
			if value == '':
				value = '1'
			qty = int( value )
			if qty > 25:
				qty = 25
				print( 'Max 25 labels allowed! Value sharped to 25.' )

			print_ondemand_label_large( 'Votre produit ouvert pour:',
				[u'[  ] ajout de matériel',
				u'[  ] contrôle qualité',
				u'',
				u'',
				u'MC Hobby SPRL' ], qty )
		elif value == '+w':
			prefix_str = raw_input(    'Préfix ou +q (ex:ELI-MEGA)             : ' )
			if value == '+q':
				continue
			counter_start = raw_input( 'N° première étiquette ou +q (ex:150021): ' )
			if counter_start == '+q':
				continue
			counter_start = int( counter_start ) 
			how_many_label= raw_input( "Combien d'étiquette ou +q             : " )
			if how_many_label == '+q':
				continue
			how_many_label = int( how_many_label )

			print_warranty_label_large( prefix_text = prefix_str, counter_start = counter_start, label_count = how_many_label )
				
		elif value.isdigit():
			print_for_product( cachedphelper, int(value) )
		else:
			print( 'Looking for product %s...' % value )
			list_products( cachedphelper, value )

	return
Esempio n. 9
0
class OrderShipApp():
	def __init__( self ):
		self.config = Config()
		self.h = CachedPrestaHelper( self.config.presta_api_url, self.config.presta_api_key, debug= False )
		self.output = PrestaOut()
		self.state  = AppState.WAIT_ORDER
		# Loaded order
		self.order    = None
		self.joined_order = [] # other order joined to the shipping
		self.customer = None
		self.carrier  = ''
		self.shipping_number = ''
		self.output.writeln( "Application initialized" )

	def test_storage_paths( self ):
		# Test the existence of data path and write access, raise exception in case of error
		self.output.writeln( "Testing paths..." )
		with open( os.path.join(self.config.order_ship_data_path, 'testfile.txt'), "a") as f:
			f.write( 'test access @ %s \r\n' % datetime.datetime.now() )

	def order_filename( self, order ):
		""" Return a tuple (filepath, filename) to use in order to store the order-data """
		# order.date_add have the format '2019-08-21 16:02:29'
		# '2019-08-21 16:02:29' => '201908'... Store by year and month
		return ( os.path.join( self.config.order_ship_data_path, order.date_add.replace('-','')[0:6] ), '%s.scan' % order.id )

	def is_order_file_exists( self, order ):
		""" Check if a data file is already stored for that order """
		path, filename = self.order_filename( order )
		try:
			os.makedirs( path )
		except:
			pass # don't raise error is path already exists
		return os.path.exists( os.path.join(path, filename) )

	def beep( self, success=False, notif=False ):
		""" Rely of audio output to signal error """
		#os.system( "mpg123 %s" % "error.mp3" )
		_name = 'error.mp3'
		if success:
			_name = 'tada.mp3'
		if notif:
			_name = 'notif.mp3'
		r_ = subprocess.Popen(['mpg123',_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE )

	def get_cmd( self, prompt='> ', debug=False ):
		""" request an command. Return a tuple (cmd_type, cmd_texte) """
		global re_add_remove_several_id
		v = ''
		while len(v)==0:
			v = v = raw_input( prompt )
			v = v.strip()

		# Manage the multiplier case
		_cmd_multiplier = 1
		g = re_add_remove_several_id.match( v )
		if g:
			# Extract the data - Qty and ID
			sign   = g.groups()[0]
			qty    = int( g.groups()[1] )
			remain = g.groups()[2]
			# Evaluate Multiplier
			_cmd_multiplier = qty if sign!="-" else -1*qty
			v = remain # command = everything after * sign

		# decode command
		_cmd_type = None
		_cmd_data = None
		_ean_type = ean_type( v )
		if _ean_type == EanType.VERB:
			# decode a VERB barre code
			_cmd_type = CMD.VERB
			_cmd_data = VERBS[v] # Convert ean to VERB text
			# Special VERB to translate in action
			if _cmd_data == 'APPEND':
				_cmd_type = CMD.APPEND_ORDER

		elif _ean_type == EanType.CARRIER:
			# decode the CARRIER barre code
			_cmd_type = CMD.SET_CARRIER
			_cmd_data = CARRIERS[v] # Convert ean to CARRIER name
		elif _ean_type == EanType.PRODUCT:
			# Retreive the product ID from EAN
			_lst = self.h.products.search_products_for_ean( v )
			if len(_lst)==0:
				_cmd_type = CMD.RAW
				_cmd_data = v
			else:
				_cmd_type = CMD.SCAN_PRODUCT
				_cmd_data = _lst[0].id
		elif _ean_type == EanType.ORDER:
			# Extract the order ID
			_cmd_type = CMD.LOAD_ORDER
			_cmd_data = int(v[-8:-1]) # Extract order ID from ean
		else: # it is EanType.UNDEFINED
			_cmd_type = CMD.RAW
			_cmd_data = v
		if debug:
			print( "Cmd type, data, mult : %s, %s, %i   - EanType %s" % (CMD(_cmd_type).name, _cmd_data, _cmd_multiplier,EanType(_ean_type).name) )
		return (_cmd_type, _cmd_data, _cmd_multiplier ) # , _ean_type )


	def check_scanned( self ):
		# Check if the scanned items correspond to the order !
		_flag = True
		self.output.writeln( '-'*80)
		self.output.writeln( 'Order   : %s' % self.order.id )
		for _joined_order in self.joined_order:
			self.output.writeln( '          joined %s' % _joined_order.id )
		self.output.writeln( 'Carrier : %s' % (self.carrier if self.carrier else '-!-') )
		if len(self.carrier)==0:
			_flag = False
		self.output.writeln( 'Ship Nr : %s' % (self.shipping_number if self.shipping_number else '-!-') )
		if len(self.shipping_number)==0:
			_flag = False
		self.output.writeln( '-'*80)
		self.output.writeln( 'Status| Scan | Order | Detail ' )
		self.output.writeln( '-'*80)
		for row in self.order.rows:
			_ok     = row.ordered_qty == self.scan[row.id_product]
			_status = 'OK' if _ok else '-!-'
			if not(_ok):
				_flag = False
			self.output.writeln( '%5s | %4i | %5i | %s ' % (_status,self.scan[row.id_product],row.ordered_qty,row) )
		return _flag

	def reset_all( self ):
		self.order = None
		self.joined_order = [] # Other order added to the shipping
		self.scan  = None
		self.customer = None
		self.state = AppState.WAIT_ORDER
		self.carrier  = ''
		self.shipping_number = ''
		self.output.reset_carbon_copy()
		for i in range( 5 ):
			print( " " ) # Do not register this message
		self.output.writeln( "Reset done!" )
		for i in range( 5 ):
			print( " " ) # Do not register this message


	def run( self ):
		""" Main application loop """
		# Test access to data_path
		self.test_storage_paths()
		self.output.set_carbon_copy()

		cmd_type,cmd_data, cmd_mult = CMD.RAW, '', 1
		while not((cmd_type==CMD.RAW) and (cmd_data.upper()=='EXIT')):
			cmd_type,cmd_data,cmd_mult = self.get_cmd( prompt="%-13s > "%AppState(self.state).name, debug=False)

			# -- Append extra info to CarbonCopy -------------------------------
			self.output.carbon_copy.append(  'CMD: %s, %s, %s' % (cmd_type,cmd_data,cmd_mult))
			# -- Reset All -----------------------------------------------------
			if (cmd_type == CMD.VERB and cmd_data == 'RESET' ):
				self.reset_all()
				continue

			# -- Loading an order ----------------------------------------------
			if (self.state == AppState.WAIT_ORDER) and (cmd_type == CMD.LOAD_ORDER):
				self.output.writeln( "Loading order %s" % cmd_data )
				# load the order
				orders = self.h.get_last_orders( int(cmd_data), 1 )
				if len( orders ) <= 0:
					self.output.writeln( "[ERROR] order %s not found!" % (cmd_data) )
					self.beep()
					continue
				# Check if the order has already been managed
				if self.is_order_file_exists( orders[0] ):
					self.output.writeln( "[ERROR] scanfile already exists for this order!" )
					self.output.writeln( "[ERROR] %s/%s" % self.order_filename( orders[0]) )
					self.beep()
					continue # Skip remaining of loading

				# Start managing the order
				self.order = orders[0]
				self.joined_order = []
				self.carrier  = ''
				self.shipping_number = ''
				self.customer = self.h.get_customer( self.order.id_customer )
				self.state    = AppState.CONTROL_ORDER

				self.output.reset_carbon_copy() # we will keep a copy of everything
				self.output.writeln( '--- Order ID : %i ---' % self.order.id )
				# self.output.writeln( 'Shop ID      : %s' % order.id_shop )
				self.output.writeln( 'Customer     : %s' % self.customer.customer_name )
				self.output.writeln( 'Cust.EMail   : %s' % self.customer.email )
				self.output.writeln( 'Order Date   : %s' % self.order.date_add )


				# Content the order
				self.scan = {}
				for row in self.order.rows:
					self.output.writeln( row )
					self.scan[row.id_product] = 0
				continue

			# -- Scan Product --------------------------------------------------
			if (cmd_type == CMD.SCAN_PRODUCT):
				if self.state != AppState.CONTROL_ORDER:
					self.output.writeln("[ERROR] No order loaded")
					self.beep()
				else:
					# Is the product in the order list
					if any( [ int(cmd_data) == int(product.id_product) for product in self.order.rows ] ):
						_items = [ product for product in self.order.rows if int(cmd_data) == int(product.id_product) ]
						_product = _items[0]
						if cmd_mult + self.scan[_product.id_product] > _product.ordered_qty :
							self.output.writeln( '[ERROR] %i * %s (%s) product CANNOT BE ADDED!' % (cmd_mult, _product.reference, _product.id_product) )
							self.output.writeln( '[ERROR] Ordered: %i, Current Scan: %i' %(_product.ordered_qty,self.scan[_product.id_product]) )
							self.beep()
						else:
							self.scan[_product.id_product] = self.scan[_product.id_product] + cmd_mult
					else:
						self.output.writeln( "[ERROR] Product %s not in the order!" % cmd_data )
						self.beep()
				continue

			# -- Append order --------------------------------------------------
			# User selected APPEND ORDER carcode
			if (cmd_type == CMD.APPEND_ORDER):
				if self.state != AppState.CONTROL_ORDER:
					self.output.writeln("[ERROR] No order loaded")
					self.beep()
				else:
					self.output.writeln("SELECT order TO APPEND to shipping!")
					self.state = AppState.APPEND_ORDER
					self.beep( notif=True )
				continue

			# user selected an order
			if (self.state == AppState.APPEND_ORDER) and (cmd_type == CMD.LOAD_ORDER):
				self.output.writeln( "Append order %s" % cmd_data )
				# load the order
				orders = self.h.get_last_orders( int(cmd_data), 1 )
				if len( orders ) <= 0:
					self.output.writeln( "[ERROR] order %s not found!" % (cmd_data) )
					self.beep()
					continue
				# Check if the order has already been managed
				if self.is_order_file_exists( orders[0] ):
					self.output.writeln( "[ERROR] scanfile already exists for this order!" )
					self.output.writeln( "[ERROR] %s/%s" % self.order_filename( orders[0]) )
					self.beep()
					continue # Skip remaining of loading

				# Start appending the loaded order
				self.joined_order.append( orders[0] )
				for row in orders[0].rows: # rows in joined order
					self.output.writeln( "Append %s" % row )
					if not( row.id_product in self.scan ):
						self.scan[row.id_product] = 0
					_matching_rows = [ _row for _row in self.order.rows if _row.id_product == row.id_product ]
					if len( _matching_rows )>0:
						_matching_rows[0].ordered_qty += row.ordered_qty # Appending qty to existing order's row
					else:
						self.order.rows.append( row )


				self.output.writeln( "Order %i succesfuly added" % orders[0].id )
				self.state = AppState.CONTROL_ORDER # Return to control order state
				continue

			# user selected CANCEL BarCode
			if (self.state == AppState.APPEND_ORDER) and (cmd_type == CMD.VERB and cmd_data == 'CANCEL' ):
				self.output.writeln( "Order appending canceled!")
				self.state = AppState.CONTROL_ORDER
				continue

			# -- Capture Carrier -----------------------------------------------
			if (cmd_type == CMD.SET_CARRIER ):
				if self.state != AppState.CONTROL_ORDER:
					self.output.writeln("[ERROR] No order loaded")
					self.beep()
				else:
					self.state = AppState.WAIT_SHIPPING
					self.carrier = cmd_data
					self.beep( notif=True )
				continue

			# -- Capture Number -----------------------------------------------
			if ((cmd_type == CMD.RAW) and (self.state == AppState.WAIT_SHIPPING) ):
				if len(cmd_data)>0 :
					self.shipping_number = cmd_data
					# GetBack to previous state
					self.state = AppState.CONTROL_ORDER
				continue

			# -- Check ---------------------------------------------------------
			if (cmd_type == CMD.VERB and cmd_data == 'CHECK' ):
				if self.state != AppState.CONTROL_ORDER:
					self.output.writeln("[ERROR] No order loaded")
					self.beep()
				else:
					# Did it worked properly ?
					if not( self.check_scanned() ):
						self.beep()
					else:
						self.beep( success=True )
				continue

			# -- Finalize ------------------------------------------------------
			if (cmd_type == CMD.VERB and cmd_data == 'FINALIZE' ):
				if self.state != AppState.CONTROL_ORDER:
					self.output.writeln("[ERROR] No order loaded")
					self.beep()
				else:
					if not( self.check_scanned() ):
						self.beep()
						continue
					self.output.writeln("")
					self.output.writeln("ORDER ID %i CHECK SUCCESSFULLY" % self.order.id )
					self.output.writeln("CUSTOMER       : %s" % self.customer.customer_name )
					self.output.writeln("OPERATION DATE : %s" % datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") )
					# Save the scan file.
					_path, _filename = self.order_filename(self.order)
					self.output.save_carbon_copy( os.path.join( _path, _filename ) )
					# Save all the joined order
					for _joined_order in self.joined_order:
						_joined_filename =  os.path.join( *(self.order_filename(_joined_order) ))
						with codecs.open( _joined_filename , 'w', 'utf-8' ) as f:
							f.write( '--- Order ID : %s ---\r\n' % _joined_order.id )
							f.write( 'JOINED TO ORDER : %s\r\n' % self.order.id )
							f.write( 'SEE SCAN : %s\r\n' % os.path.join( _path, _filename ) ) # Mention original filename1
							f.write( 'OPERATION DATE : %s' % datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") )
					# Reset for next scan session
					self.reset_all()
					self.beep( success=True )
					continue

			# == Reaching this Point --> Error ===s==============================
			self.output.writeln("[ERROR] UNKNOWN instruction scan or ean scan!")
			self.beep()

		self.output.writeln( 'User exit!' )
Esempio n. 10
0
from prestaapi import PrestaHelper, CachedPrestaHelper, OrderStateList
from output import PrestaOut
from config import Config
from pprint import pprint
import logging
import sys, os, codecs
import re, subprocess
import signal
import datetime
# debugging
from xml.etree import ElementTree
#
from enum import Enum

config = Config()
h = CachedPrestaHelper( config.presta_api_url, config.presta_api_key, debug= False )
#print ("#products = %i" % ( len( h.products ) ) )

class AppState( Enum ):
	WAIT_ORDER    = 0
	CONTROL_ORDER = 1
	WAIT_SHIPPING = 2
	CONTROLED     = 3
	APPEND_ORDER  = 4 # Wait state to append an order

class CMD( Enum ):
	RAW = 0
	VERB = 1 # The text value is one of the Verbs dic
	SET_CARRIER = 2 # Setting the CARRIERS (one of CARRIERS dic), so setting the CARRIER
	LOAD_ORDER  = 3 # Loading an ORDER
	SCAN_PRODUCT= 4 # Scanning a product
Esempio n. 11
0
def main():
    def progressHandler(prestaProgressEvent):
        if prestaProgressEvent.is_finished:
            print('%s' % prestaProgressEvent.msg)
        else:
            print('%i/%i - %s' %
                  (prestaProgressEvent.current_step,
                   prestaProgressEvent.max_step, prestaProgressEvent.msg))

    def initialize_globals():
        """ Initialize the global var @ startup or @ reload """
        global ID_SUPPLIER_PARAMS
        _item = cachedphelper.suppliers.supplier_from_name("PARAMS")
        #for _item in cachedphelper.suppliers:
        #	print( '%i - %s' % (_item.id,_item.name) )
        if _item != None:
            ID_SUPPLIER_PARAMS = _item.id
            print('Catched PARAMS supplier :-). ID: %i' % ID_SUPPLIER_PARAMS)

# A CachedPrestaHelper is a PrestaHelper with cache capabilities

    cachedphelper = CachedPrestaHelper(config.presta_api_url,
                                       config.presta_api_key,
                                       debug=False,
                                       progressCallback=progressHandler)
    # Force loading cache
    #   cachedphelper.load_from_webshop()

    #tester = CachedPrestaHelperTest( cachedphelper )
    #tester.test_cache()
    print('******************************************************************')
    print('*  Cache statistics                                              *')
    print('******************************************************************')
    print('Type of Helper is %s' % type(cachedphelper))
    print('#Carriers = %s' % len(cachedphelper.carriers))
    print('#OrderStates = %s' % len(cachedphelper.order_states))
    print('#Products = %i' % len(cachedphelper.products))
    print('#suppliers = %i' % len(cachedphelper.suppliers))
    print('#categories = %i' % len(cachedphelper.categories))
    print('#stock availables = %i' % len(cachedphelper.stock_availables))
    print('#product suppliers available = %i' %
          len(cachedphelper.product_suppliers))
    print('******************************************************************')
    print('')
    initialize_globals()

    #print('mise à jour des qty' )
    #cachedphelper.stock_availables.update_quantities()
    #print( 'Voila, c est fait' )

    value = ''
    while value != '+q':
        print('=' * 40)
        print('  +r : reload cache           | +s          : save cache')
        print('  +12: ean12 to ean13         | +e          : create ean13')
        print('  id : id product to print    | partial_code: to search')
        print('  +ol: On demand label (Large)| +al         : address label')
        print(
            '  +os: On demand label (Short)| +openl      : open for... label')
        print('  +ok: On demand label (King) | +w          : Warranty')
        print('  +q : quit ')
        print('=' * 40)
        print('')
        value = raw_input('What to do: ')

        if value == '+q':
            pass
        elif value == '+r':
            print('Contacting WebShop and reloading...')
            cachedphelper.load_from_webshop()
            initialize_globals()  # reinit global variables
        elif value == '+s':
            print('Saving cache...')
            cachedphelper.save_cache_file()
        elif value == '+12':
            ean12_to_ean13()
        elif value == '+e':
            product_id_to_ean13()
        elif value == '+ol':  #On_demand Large label
            ondemand_label_large()
        elif value == '+os':  #On_demand Short label
            ondemand_label_short()
        elif value == '+ok':  #On_demand King Size Label
            line1 = raw_input('Line 1: ')
            if line1 == '+q' or line1 == '':
                continue
            line2 = raw_input('Line 2: ')

            print_ondemand_label_kingsize(line1, line2)
        elif value == '+al':  # adress Label
            value = raw_input('How many labels or +q: ')
            if value == '+q' or value == '0':
                continue
            if value == '':
                value = '1'
            qty = int(value)
            if qty > 25:
                qty = 25
                print('Max 25 labels allowed! Value sharped to 25.')

            print_ondemand_label_large('MC Hobby SPRL', [
                unicode(config.company_address[0]),
                unicode(config.company_address[1]),
                unicode(config.company_address[2]),
                unicode(u'TVA/VAT: %s' % config.company_vat),
                unicode(u'Phone  : %s' % config.company_phone),
                unicode(u'Web    : %s' % config.company_url)
            ], qty)

        elif value == '+openl':
            value = raw_input('How many labels or +q: ')
            if value == '+q' or value == '0':
                continue
            if value == '':
                value = '1'
            qty = int(value)
            if qty > 25:
                qty = 25
                print('Max 25 labels allowed! Value sharped to 25.')

            print_ondemand_label_large('Votre produit ouvert pour:', [
                u'[  ] ajout de matériel', u'[  ] contrôle qualité', u'', u'',
                u'MC Hobby SPRL'
            ], qty)
        elif value == '+w':
            prefix_str = raw_input('Préfix ou +q (ex:ELI-MEGA)             : ')
            if value == '+q':
                continue
            counter_start = raw_input(
                'N° première étiquette ou +q (ex:150021): ')
            if counter_start == '+q':
                continue
            counter_start = int(counter_start)
            how_many_label = raw_input(
                "Combien d'étiquette ou +q             : ")
            if how_many_label == '+q':
                continue
            how_many_label = int(how_many_label)

            print_warranty_label_large(prefix_text=prefix_str,
                                       counter_start=counter_start,
                                       label_count=how_many_label)

        elif value.isdigit():
            print_for_product(cachedphelper, int(value))
        else:
            print('Looking for product %s...' % value)
            list_products(cachedphelper, value)

    return
Esempio n. 12
0
class MyApp:
	def __init__( self, screen ):
		self.screen = screen 
		(self.height, self.width) = screen.getmaxyx()
		self.subwin = [] # Subwin list
		self.create_subwin()

		# Create a SysLog handler
		self.logger = logging.getLogger()
		self.logger.setLevel( logging.DEBUG )
		# Follow the log with
		#    tail -f /var/log/syslog 
		# formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s')
		#    also mention the python filename in the log
		formatter = logging.Formatter( os.path.basename(__file__)+' :: %(levelname)s :: %(message)s')
		sys_handler = SysLogHandler( address = '/dev/log')
		sys_handler.setLevel( LOGGING_LEVEL )
		sys_handler.setFormatter( formatter )
		self.logger.addHandler( sys_handler )

		self.logger.info( 'Starting app' )
		self.config = Config()
		self.cachedphelper  = CachedPrestaHelper( self.config.presta_api_url, self.config.presta_api_key, debug = False ) #, progressCallback = progressHandler )
		# initialize global variables
		self.initialize_globals()

	def initialize_globals( self ):
		""" Initialize the global var @ startup or @ reload """
		global ID_SUPPLIER_PARAMS
		_item = self.cachedphelper.suppliers.supplier_from_name( "PARAMS" )
		#for _item in cachedphelper.suppliers:
		#	print( '%i - %s' % (_item.id,_item.name) )
		if _item != None:
			ID_SUPPLIER_PARAMS = _item.id
			self.logger.info( 'Catched PARAMS supplier :-). ID: %i' % ID_SUPPLIER_PARAMS )	

	def create_subwin(self):
		self.wresult = curses.newwin(self.height-1,self.width,0,0) # NLines, NCols, begin_y, begin_x
		self.wresult.border()
		self.wresult.addstr(0,2,"[ Result ]")
		self.wresult.addstr(1,1,"%i , %i" % self.wresult.getmaxyx() )
		self.subwin.append( (self.wresult,self.wresult_redraw) )

		self.status = curses.newwin(2,self.width,self.height-1,0) # min 2 lines height!!!

	def wresult_redraw(self):
		""" redraw the subwin background """
		self.wresult.clear()
		self.wresult.border()
		self.wresult.addstr( 0, 2, "[ Result ]" )

	#def draw_screen(self)

	def status_redraw( self, input_text=None, input_data=None, info=None ):
		""" redraw the status bar """
		self.status.addstr( 0, 0, " "*self.width, curses.A_REVERSE )

		# Only draw information in the second part of the screen
		info = '| +h for Help' if info==None else '| %s'%info
		info = info + ' '*(self.width//2-len(info))
		self.status.addstr( 0, self.width//2, '%s' % info, curses.A_REVERSE )
		
		# Draw input_text and input_data in the first part of the screen
		if input_text or input_data:
			_s = "%s%s" % (input_text,input_data if input_data else '')
			self.status.addstr( 0, 1, _s, curses.A_REVERSE )

		self.status.refresh()

	def screen_redraw( self ):
		""" Draw every subwindow THEN refresh the whole terminal """
		self.screen.clear()		
		# full screen redraw
		for win, redraw in self.subwin:
		    redraw()
		self.status_redraw()
		# Refresh the output
		self.refresh()

	def refresh( self ):
		""" makes curses refreshing the whole terminal content """ 
		for win, redraw  in self.subwin:
			win.refresh()
		self.status.refresh()

	def input( self, text = '?' ):
		""" capture a string from the keyboard, each characters in the status bar.
		returns a tuple (input_string,last_ch_ascii_code) """
		_r = ''
		self.status_redraw( input_text=text, input_data=_r )

		ch = 0
		while True:
			ch = self.status.getch()
			self.logger.debug( 'getch returned %i' % ch )
			if ch in (13,10): # CR/LF
				break
			elif ch == 127: # backspace
			    if len(_r)>0:
					_r = _r[:-1]
			elif ch == 27: # escape
				if len(_r)>0: # First time, we clear the input
					_r = ''
				else:
					break # Second time (so when empty): we exit the input 
			elif 31 <= ch < 256:
				_r = _r + chr(ch)

			# Display the current value
			self.status_redraw( input_text=text, input_data=_r )
			self.status.refresh()

		# Clear input field zone in the status bar
		self.status_redraw( input_text=None, input_data=None )

		self.logger.debug( 'input() returns with "%s" and last key %i' % (_r,ch) )
		return (_r,ch)

	def search_products( self, key=None, ean=None, id=None ):
		""" Search for a product based on its partial reference code (key) -OR- its ean -OR- product ID.

		:return: None or a list of product """
		
		result = None
		if key:
			assert isinstance( key, str ), 'Key must be a string'
			if len( key ) < 3:
				print( 'searching product requires at least 3 characters' )
				return
			result = self.cachedphelper.products.search_products_from_partialref( key )
		elif ean:
			assert isinstance( ean, str ), 'Key must be a string'
			result = self.cachedphelper.products.search_products_for_ean( ean )
		elif id:
			assert isinstance( id, int ), 'ID must be an integer'
			_r = self.cachedphelper.products.product_from_id( id )
			result = [_r] if _r else None

		return result

	def display_products( self, products, auto_select=False ):
		""" Display a list of products in the wresult Windows 

		:param products: list of product to display.
		:param auto_select: automaticaly select the first row WHEN it is the unique row! """
		self.logger.debug('display_products')
		iTopIndex = 0 # Index of the TOP record in the products list
		iSelected = 0 # Index of the ITEM currently selected 
		hClient = self.wresult.getmaxyx()[0] - 2 # Height of the client area
		wclient = self.wresult.getmaxyx()[1] - 2
		while products and len( products )>0: # At least one item
			self.wresult_redraw()
			iRow = 0
			for i in range(iTopIndex,iTopIndex+hClient):
				# self.logger.debug( '%i' % i)
				if i >= len(products):
					continue
				item = products[i]
				_s = '%4i: %s (%6.2f) %6.2f EUR' % (item.id,item.reference.ljust(20),item.price,item.price*1.21) 
				self.wresult.addstr( iRow+1,1, _s, curses.A_REVERSE if i == iSelected else 0 )
				iRow += 1
			self.wresult.refresh()

			# auto_select
			if len( products )==1 and auto_select:
				return products[0]

			# user input
			self.status_redraw( input_text='browsing result...')
			ch = self.status.getch()
			self.logger.debug( 'getch returned %i' % ch )
			if ch in (13,10): # CR/LF
				return products[iSelected]
			#elif ch == 27: #ESC -- also returned with escape sequence....
			#	return None
			elif ch == 66: # arrow down
				# Select next
				iSelected += 1
				if iSelected >= len( products ):
					iSelected = len( products )-1
				# Keep selected row visible
				if iSelected >= (iTopIndex + hClient):
					iTopIndex += 1
			elif ch == 65: # arrow up
				iSelected -= 1
				if iSelected <= 0:
					iSelected = 0
				# Keep selected row visible
				if iSelected < iTopIndex:
					iTopIndex = iSelected

		# Always return something
		return None 


	def run( self ):
		self.screen_redraw()

		while True:
			(_cmd,_ch) = self.input( text='Cmd?' )

			# special commands
			if _cmd.upper() == '+Q':
				break # Exit the software
			elif _cmd.upper() == '+R':
				self.status_redraw( info='Contacting WebShop and reloading...' )
				self.cachedphelper.load_from_webshop()
				self.initialize_globals() # reinit global variables
				self.screen_redraw()
				self.status_redraw( info='Data reloaded!')
				sleep( 1 )
				continue	
			elif _cmd.upper() == '+S':
				print( 'Saving cache...' )
				self.status_redraw( info = 'Saving cache...')
				self.cachedphelper.save_cache_file()
				self.screen_redraw()
				self.status_redraw( info='Data saved!' )
				sleep( 1 )
				continue
			elif _cmd.upper() == '+H':
				# Display the Help
				self.wresult_redraw()
				for idx, line in enumerate( HELP_MESSAGE.split('\n') ):
					self.wresult.addstr( 1+idx,1, line )
				self.wresult.refresh()
				self.status_redraw(input_text='Press return to continue')
				self.wresult.getch()
				self.wresult_redraw()

					
			_l = None # List of products
			if _cmd.isdigit():
				if len(_cmd)<=5: # we are looking for a product ID
					_l = self.search_products( id=int(_cmd) )
				else:
					_l = self.search_products( ean=_cmd )
			else:
				if len(_cmd)<3:
					self.status_redraw( input_text='Min. 3 chars!!!' )
					sleep( 1 )
				else:
					_l = self.search_products( key=_cmd )
			# Show the product on the screen
			self.display_products( _l, auto_select=True )
			
			self.refresh()
Esempio n. 13
0
def main2():
	def progressHandler( prestaProgressEvent ):
		if prestaProgressEvent.is_finished:
			print( '%s' %prestaProgressEvent.msg )
		else:
			print( '%i/%i - %s' % ( prestaProgressEvent.current_step, prestaProgressEvent.max_step, prestaProgressEvent.msg ) )


    
    # A CachedPrestaHelper is a PrestaHelper with cache capabilities	
	cachedphelper = CachedPrestaHelper( config.presta_api_url, config.presta_api_key, debug = False, progressCallback = progressHandler )
	# Force loading cache
	#   cachedphelper.load_from_webshop()
	
	#tester = CachedPrestaHelperTest( cachedphelper )
	#tester.test_cache()
	print( '******************************************************************' )
	print( '*  Cache statistics                                              *' )
	print( '******************************************************************' )
	print( 'Type of Helper is %s' % type(cachedphelper) )
	print( '#Carriers = %s' % len(cachedphelper.carriers) )
	print( '#OrderStates = %s' % len( cachedphelper.order_states ) )
	print( '#Products = %i' % len( cachedphelper.products ) )
	print( '#suppliers = %i' % len( cachedphelper.suppliers ) )
	print( '#categories = %i' % len( cachedphelper.categories ) )
	print( '#stock availables = %i' % len( cachedphelper.stock_availables ) )
	print( '#product suppliers available = %i' % len( cachedphelper.product_suppliers ) )
	print( '******************************************************************' )
	print( '' )		
	initialize_globals()

	#print('mise à jour des qty' )
	#cachedphelper.stock_availables.update_quantities()
	#print( 'Voila, c est fait' )
	
	value = ''
	while value != '+q':
		print( '='*40 )
		print( '  +r : reload cache           | +s          : save cache' )
		print( '  +q : quit ' )
		print( '='*40 )
		print( '' )
		value = raw_input( 'What to do: ' )
		
		if value == '+q':
			pass
		elif value == '+r':
			print( 'Contacting WebShop and reloading...' )
			cachedphelper.load_from_webshop()
			initialize_globals() # reinit global variables	
		elif value == '+s':
			print( 'Saving cache...' )
			cachedphelper.save_cache_file()
				
		elif value.isdigit():
			if len(value)<=5: # we are looking for a product ID
				list_products( cachedphelper, id=int(value) )
			else:
				list_products( cachedphelper, ean=value )
		else:
			print( 'Looking for product %s...' % value )
			list_products( cachedphelper, key=value )

	return