Esempio n. 1
0
class MatchOff_Frame ( wx.Frame ):
    
    def __init__( self, main_window ):
        wx.Frame.__init__ ( self, main_window, id = wx.ID_ANY, title = u"Match Off Application", pos = wx.DefaultPosition, size = wx.Size( 509,498 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
        
        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )
        self.SetFont( wx.Font( 11, 70, 90, 90, False, wx.EmptyString ) )
        
        self.init_ui()
        self.make_menu()
        self.connect_events()
        
        self.Bind(EVT_MATCHOFF, self.on_update)
        
        self.colnames = list(uppercase)
        
        
    def init_ui(self):
        frame_sizer = wx.BoxSizer( wx.VERTICAL )
        
        self.main_panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
        mp_sizer = wx.BoxSizer( wx.VERTICAL )
        
        input_fg_sizer = wx.FlexGridSizer( 0, 2, 0, 0 )
        input_fg_sizer.AddGrowableCol( 1 )
        input_fg_sizer.SetFlexibleDirection( wx.BOTH )
        input_fg_sizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )
        
        self.fchooser_text = wx.StaticText( self.main_panel, wx.ID_ANY, u"Select File:", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.fchooser_text.Wrap( -1 )
        self.fchooser_text.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        
        input_fg_sizer.Add( self.fchooser_text, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
        
        self.file_chooser = wx.FilePickerCtrl( self.main_panel, wx.ID_ANY, wx.EmptyString, u"Select a file", u"*.*", wx.DefaultPosition, wx.DefaultSize, wx.FLP_DEFAULT_STYLE )
        self.file_chooser.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        self.file_chooser.SetToolTipString( u"Click to select a file" )
        
        input_fg_sizer.Add( self.file_chooser, 0, wx.ALL|wx.EXPAND, 5 )
        
        self.ccy_label = wx.StaticText( self.main_panel, wx.ID_ANY, u"Currency Column:", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.ccy_label.Wrap( -1 )
        self.ccy_label.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        
        input_fg_sizer.Add( self.ccy_label, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
        
        self.ccy_ctrl = wx.TextCtrl( self.main_panel, wx.ID_ANY, u"G", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.ccy_ctrl.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        self.ccy_ctrl.SetToolTipString( u"Enter Column containing currency" )
        
        input_fg_sizer.Add( self.ccy_ctrl, 0, wx.ALL|wx.EXPAND, 5 )
        
        self.bal_label = wx.StaticText( self.main_panel, wx.ID_ANY, u"Balance Column:", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.bal_label.Wrap( -1 )
        self.bal_label.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        
        input_fg_sizer.Add( self.bal_label, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )
        
        self.bal_ctrl = wx.TextCtrl( self.main_panel, wx.ID_ANY, u"H", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.bal_ctrl.SetToolTipString( u"Enter column containing balances" )
        
        input_fg_sizer.Add( self.bal_ctrl, 0, wx.ALL|wx.EXPAND, 5 )
        
        mp_sizer.Add( input_fg_sizer, 0, wx.EXPAND|wx.ALL, 5 )
        
        btn_sizer = wx.BoxSizer( wx.HORIZONTAL )
        
        self.validate_btn = wx.Button( self.main_panel, wx.ID_ANY, u"Validate Input", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.validate_btn.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        self.validate_btn.SetToolTipString( u"Click to confirm your inputs are correct" )
        
        btn_sizer.Add( self.validate_btn, 0, wx.ALL, 5 )
        
        self.match_btn = wx.Button( self.main_panel, wx.ID_ANY, u"Match Off", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.match_btn.SetFont( wx.Font( 10, 70, 90, 90, False, wx.EmptyString ) )
        self.match_btn.Enable( False )
        self.match_btn.Hide()
        self.match_btn.SetToolTipString( u"Click to start match off" )
        
        btn_sizer.Add( self.match_btn, 0, wx.ALL, 5 )
        
        self.stop_btn = wx.Button( self.main_panel, wx.ID_ANY, u"Stop Matching", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.stop_btn.Enable( False )
        self.stop_btn.Hide()
        
        btn_sizer.Add( self.stop_btn, 0, wx.ALL, 5 )
        
        mp_sizer.Add( btn_sizer, 0, wx.ALIGN_RIGHT, 5 )
        
        self.output_ctrl = wx.TextCtrl( self.main_panel, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 100,100 ), wx.TE_MULTILINE|wx.TE_READONLY|wx.TE_WORDWRAP )
        self.output_ctrl.SetFont( wx.Font( 12, 70, 90, 90, False, wx.EmptyString ) )
        
        mp_sizer.Add( self.output_ctrl, 1, wx.ALL|wx.ALIGN_CENTER_HORIZONTAL|wx.EXPAND, 5 )
        
        self.main_panel.SetSizer( mp_sizer )
        self.main_panel.Layout()
        mp_sizer.Fit( self.main_panel )
        frame_sizer.Add( self.main_panel, 1, wx.EXPAND |wx.ALL, 5 )
        
        self.SetSizer( frame_sizer )
        self.Layout()
        
        
    def make_menu(self):
        self.menu_bar = wx.MenuBar( 0 )
        self.file_menu = wx.Menu()
        self.open_mitem = wx.MenuItem( self.file_menu, wx.ID_ANY, u"&Open", wx.EmptyString, wx.ITEM_NORMAL )
        self.file_menu.AppendItem( self.open_mitem )
        
        self.file_menu.AppendSeparator()
        
        self.about_mitem = wx.MenuItem( self.file_menu, wx.ID_ANY, u"&About", wx.EmptyString, wx.ITEM_NORMAL )
        self.file_menu.AppendItem( self.about_mitem )
        
        self.file_menu.AppendSeparator()
        
        self.exit_mitem = wx.MenuItem( self.file_menu, wx.ID_ANY, u"&Exit", wx.EmptyString, wx.ITEM_NORMAL )
        self.file_menu.AppendItem( self.exit_mitem )
        
        self.menu_bar.Append( self.file_menu, u"&File" ) 
        
        self.tutorial_menu = wx.Menu()
        self.tutorial_mitem = wx.MenuItem( self.tutorial_menu, wx.ID_ANY, u"&tutorial", wx.EmptyString, wx.ITEM_NORMAL )
        self.tutorial_menu.AppendItem( self.tutorial_mitem )
        
        self.menu_bar.Append( self.tutorial_menu, u"&Tutorial" ) 
        
        self.SetMenuBar( self.menu_bar )
        
        self.statusbar = self.CreateStatusBar( 1, wx.ST_SIZEGRIP, wx.ID_ANY )
        
        self.Centre( wx.BOTH )
        
        
    def connect_events(self):
        self.validate_btn.Bind( wx.EVT_BUTTON, self.on_validate )
        self.match_btn.Bind( wx.EVT_BUTTON, self.on_matchoff )
        self.Bind( wx.EVT_MENU, self.on_open, id = self.open_mitem.GetId() )
        self.Bind( wx.EVT_MENU, self.on_about, id = self.about_mitem.GetId() )
        self.Bind( wx.EVT_MENU, self.on_exit, id = self.exit_mitem.GetId() )
        self.Bind( wx.EVT_MENU, self.on_tutorial, id = self.tutorial_mitem.GetId() )
        self.file_chooser.Bind( wx.EVT_FILEPICKER_CHANGED, self.on_file_chooser )
        self.stop_btn.Bind( wx.EVT_BUTTON, self.on_stop )
    
    
    def on_file_chooser( self, event ):
        f = self.file_chooser.GetTextCtrlValue()
        fname, dirname = os.path.basename(f), os.path.dirname(f)
        
        self.make_matcher(fname, dirname)
        
          
    
    def on_validate( self, event ):
        
        if not self.confirm_matcher():
            return
        
        if not self.check_col_val():
            self.display_error_dlg("Either currency or balance column entered is invalid.")
            return  
        
        else :            
            bal_col_num = self.colnames.index( self.col_text )
            ccy_col_num = self.colnames.index( self.ccy_text )
            
            if not (bal_col_num and ccy_col_num and bal_col_num < self.m.ncols and ccy_col_num < self.m.ncols ):
                self.display_error_dlg( "Either currency or balance column entered is invalid." )
                return
            
            if self.make_matcher_input_cols( ccy_col_num, bal_col_num ):
                self.validate_btn.Disable()
    
      
    def on_matchoff(self, evt):
        
        if not self.confirm_matcher():
            return
        
        matcher_thread = MatcherThread(self)
        matcher_thread.start()
        
        self.file_chooser.SetPath("")
         
        self.match_btn.Disable()
        self.match_btn.Hide()
        
        self.stop_btn.Enable()
        self.stop_btn.Show()
        self.Layout()
    
     
    def on_update(self,evt):
        self.output_ctrl.AppendText(  evt.get_value()  )
    
    
    def on_open( self, event ):
        self.dirname = ''
            
        dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
        
        if dlg.ShowModal() == wx.ID_OK:
                fname = dlg.GetFilename()
                self.dirname = dlg.GetDirectory()
                
                self.make_matcher(fname, self.dirname)
                
        dlg.Destroy()
    
    
    def on_stop( self, event ):
        event.Skip()
        
        
    def make_matcher(self, fname, dirname):
        
                if self.verify_file_ext(fname):
                    self.filename = os.path.join(dirname, fname)
                    
                else:
                    self.display_error_dlg("Invalid file selected.\nPlease select a valid excel 97-2003 file!") 
                    return
                    
                if self.verify_filename():
                    self.m = Matcher(self.filename)
                    self.m.dosetup()
    
              
                
    def on_about( self, event ):
        self.display_error_dlg(msg="An application to match off credits and debits", caption="Information")
    
    
    
    def on_exit( self, event ):
        self.Destroy()
    
    
    
    def on_tutorial( self, event ):
        event.Skip()

    
    
    def verify_file_ext(self, name):
        extension = os.path.splitext(name)[1] 
        return extension.lower() == ".xls"
    
    
    
    def display_error_dlg(self, msg, caption="Error!!"):
        dlg = wx.MessageDialog(self, message=msg, caption=caption, style=wx.OK)
        dlg.ShowModal()
        dlg.Destroy() 
        
    
    
    def verify_filename(self):
        if self.filename and self.verify_file_ext(self.filename):
            return True
        
        else:
            self.display_error_dlg("No file selected!")
            return False
    
    
    
    def validate_inputs(self):
        
        if not self.confirm_matcher():
            return
        
        if not self.check_col_val():
            self.display_error_dlg("Either currency or balance column entered is invalid.")
            return  
        
        else :            
            bal_col_num = self.colnames.index( self.col_text )
            ccy_col_num = self.colnames.index( self.ccy_text )
            
            if not (bal_col_num and ccy_col_num and bal_col_num < self.m.ncols and ccy_col_num < self.m.ncols ):
                self.display_error_dlg( "Either currency or balance column entered is invalid." )
                return
            
            if not self.make_matcher_input_cols( ccy_col_num, bal_col_num ):
                return
        
              
        
    def confirm_matcher(self):
        
        self.m = getattr(self, "m", None)
        
        if not (self.m and self.m.filename):
            self.display_error_dlg('No Valid File Chosen. Please click "File" in the menubar and select "Open".')
            return False
        
        return True



    def check_col_val(self):
        
        col,ccy = self.bal_ctrl.GetValue(), self.ccy_ctrl.GetValue()
        
        if col and ccy: 
        
            self.col_text = col.strip().upper()
            self.ccy_text = ccy.strip().upper()
        
            if self.col_text and self.ccy_text and self.col_text.isalpha()  and self.ccy_text.isalpha()\
            and self.col_text.upper() in self.colnames and self.ccy_text.upper() in self.colnames:
                return True
            
        else: 
            return False   

    
    
    def make_matcher_input_cols(self, ccy_col_num, bal_col_num):
        
        ccy = self.m.get_cell_val(4,ccy_col_num)
        
        if not ccy in self.m.FX:
            self.display_error_dlg("Selected Currency column is invalid.\nPlease input a valid currency column.")
            return False
        
        self.m.make_start_cols(ccy_col_num, bal_col_num)
        self.display_error_dlg("All inputs valid. Click 'Match Off' button to start")
        self.match_btn.Enable()
        self.match_btn.Show(True)
        self.validate_btn.Hide()
        self.Layout()
        return True