#!/usr/bin/env python
# -*- coding: CP1252 -*-
#
# generated by wxGlade 0.6.8 (standalone edition) on Thu May 18 11:06:10 2017
#

import wx, wx.grid, os, datetime, json, StringIO, csv

# begin wxGlade: dependencies
# end wxGlade

# begin wxGlade: extracode
# end wxGlade

exception_list = ["","GL Journal Entry","Separate Batch"]
exception_types = wx.grid.GridCellChoiceEditor(exception_list, True)

class MyDialect(csv.Dialect):
    strict = True
    skipinitialspace = True
    quoting = csv.QUOTE_ALL
    delimiter = ','
    quotechar = '"'
    lineterminator = '\n'


class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.Settings = wx.Panel(self, wx.ID_ANY)
        self.label_2_copy = wx.StaticText(self.Settings, wx.ID_ANY, "Input Path")
        self.button_3_copy = wx.Button(self.Settings, wx.ID_ANY, "Set Input File")
        self.INPUTPATH = wx.StaticText(self.Settings, wx.ID_ANY, "")
        self.panel_2 = wx.Panel(self, wx.ID_ANY)
        self.label_2 = wx.StaticText(self.panel_2, wx.ID_ANY, "Output Path")
        self.button_3 = wx.Button(self.panel_2, wx.ID_ANY, "Set Output File")
        self.OUTPUTPATH = wx.StaticText(self.panel_2, wx.ID_ANY, "")
        self.panel_2_copy = wx.Panel(self, wx.ID_ANY)
        self.label_2_copy_2 = wx.StaticText(self.panel_2_copy, wx.ID_ANY, "Log Path")
        self.button_3_copy_2 = wx.Button(self.panel_2_copy, wx.ID_ANY, "Set Log File")
        self.LOGPATH = wx.StaticText(self.panel_2_copy, wx.ID_ANY, "")
        self.panel_4 = wx.Panel(self, wx.ID_ANY)
        self.label_2_copy_1 = wx.StaticText(self.panel_4, wx.ID_ANY, "Period")
        self.PERIOD = wx.ComboBox(self.panel_4, wx.ID_ANY, choices=["", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"], style=wx.CB_DROPDOWN | wx.CB_DROPDOWN)
        self.OUTPUTPATH_copy_1 = wx.StaticText(self.panel_4, wx.ID_ANY, "")
        self.label_3 = wx.StaticText(self.panel_4, wx.ID_ANY, "Year")
        self.YEAR = wx.SpinCtrl(self.panel_4, wx.ID_ANY, "", min=0, max=100, style=wx.TE_READONLY)
        self.panel_4_copy = wx.Panel(self, wx.ID_ANY)
        self.OUTPUTPATH_copy_1_copy = wx.StaticText(self.panel_4_copy, wx.ID_ANY, "")
        self.label_2_copy_1_copy_copy = wx.StaticText(self.panel_4_copy, wx.ID_ANY, "Batch Handling")
        self.HANDLING = wx.ComboBox(self.panel_4_copy, wx.ID_ANY, choices=["Hold", "Release Now"], style=wx.CB_DROPDOWN | wx.CB_DROPDOWN)
        self.panel_1 = wx.Panel(self, wx.ID_ANY)
        self.button_3_copy_1 = wx.Button(self.panel_1, wx.ID_ANY, "Process")
        self.panel_3 = wx.Panel(self, wx.ID_ANY)
        self.label_1 = wx.StaticText(self.panel_3, wx.ID_ANY, "GL Journal Entry Vendors")
        self.REPORTVIEWER = wx.grid.Grid(self, wx.ID_ANY, size=(1, 1))

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.setInput, self.button_3_copy)
        self.Bind(wx.EVT_BUTTON, self.setOutput, self.button_3)
        self.Bind(wx.EVT_BUTTON, self.setLog, self.button_3_copy_2)
        self.Bind(wx.EVT_SPINCTRL, self.saveYear, self.YEAR)
        self.Bind(wx.EVT_BUTTON, self.processFile, self.button_3_copy_1)
        self.Bind(wx.grid.EVT_GRID_CMD_CELL_CHANGE, self.saveReport, self.REPORTVIEWER)
        # end wxGlade
        self.db = { "OUTPUTPATH": "",
                    "EXCEPTIONS": [],
                    "YEAR": datetime.datetime.now().year,
                    "LOGPATH": "",
                    "GLREF": "",
                    "CLEARINGACCT": "",
                    "CLEARINGSUBACCT": "",
                  }
        try:
            i=open('./settings.txt','r')
            a=json.loads(i.read())
            i.close()
            self.db.update(a)
        except IOError:
            pass
        self.save_exceptions = False
        self.OUTPUTPATH.Label = self.db["OUTPUTPATH"]
        self.LOGPATH.Label = self.db["LOGPATH"]
        self.exceptions = self.db["EXCEPTIONS"]
        self.loadExceptions(self.exceptions)

        self.save_exceptions = True
        
        year = datetime.datetime.now().year
        self.save_year = False
        self.YEAR.SetRange(year-10,year+10)
        self.YEAR.Value = self.db['YEAR']
        self.save_year = True
        self.input_files = []

    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("Transaction Importer")
        self.SetSize((410, 406))
        self.PERIOD.SetSelection(0)
        self.HANDLING.SetSelection(0)
        self.panel_3.SetMinSize((422, 13))
        self.REPORTVIEWER.CreateGrid(0, 3)
        self.REPORTVIEWER.SetRowLabelSize(0)
        self.REPORTVIEWER.EnableDragColSize(0)
        self.REPORTVIEWER.EnableDragRowSize(0)
        self.REPORTVIEWER.EnableDragGridSize(0)
        self.REPORTVIEWER.SetColLabelValue(0, "Vendor Name")
        self.REPORTVIEWER.SetColLabelValue(1, "Vendor ID")
        self.REPORTVIEWER.SetColLabelValue(2, "Exception Type")
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_3_copy = wx.BoxSizer(wx.HORIZONTAL)
        sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8_copy_1_copy = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8_copy_1 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8_copy_2 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8 = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8_copy = wx.BoxSizer(wx.HORIZONTAL)
        sizer_8_copy.Add(self.label_2_copy, 0, 0, 0)
        sizer_8_copy.Add(self.button_3_copy, 0, 0, 0)
        sizer_8_copy.Add(self.INPUTPATH, 0, 0, 0)
        self.Settings.SetSizer(sizer_8_copy)
        sizer_1.Add(self.Settings, 0, wx.EXPAND, 0)
        sizer_8.Add(self.label_2, 0, 0, 0)
        sizer_8.Add(self.button_3, 0, 0, 0)
        sizer_8.Add(self.OUTPUTPATH, 0, 0, 0)
        self.panel_2.SetSizer(sizer_8)
        sizer_1.Add(self.panel_2, 0, wx.EXPAND, 0)
        sizer_8_copy_2.Add(self.label_2_copy_2, 0, 0, 0)
        sizer_8_copy_2.Add(self.button_3_copy_2, 0, 0, 0)
        sizer_8_copy_2.Add(self.LOGPATH, 0, 0, 0)
        self.panel_2_copy.SetSizer(sizer_8_copy_2)
        sizer_1.Add(self.panel_2_copy, 0, wx.EXPAND, 0)
        sizer_8_copy_1.Add(self.label_2_copy_1, 0, 0, 0)
        sizer_8_copy_1.Add(self.PERIOD, 0, 0, 0)
        sizer_8_copy_1.Add(self.OUTPUTPATH_copy_1, 0, 0, 0)
        sizer_8_copy_1.Add(self.label_3, 0, 0, 0)
        sizer_8_copy_1.Add(self.YEAR, 0, 0, 0)
        self.panel_4.SetSizer(sizer_8_copy_1)
        sizer_1.Add(self.panel_4, 0, wx.EXPAND, 0)
        sizer_8_copy_1_copy.Add(self.OUTPUTPATH_copy_1_copy, 0, 0, 0)
        sizer_8_copy_1_copy.Add(self.label_2_copy_1_copy_copy, 0, 0, 0)
        sizer_8_copy_1_copy.Add(self.HANDLING, 0, 0, 0)
        self.panel_4_copy.SetSizer(sizer_8_copy_1_copy)
        sizer_1.Add(self.panel_4_copy, 0, wx.EXPAND, 0)
        sizer_2.Add(self.button_3_copy_1, 0, 0, 0)
        self.panel_1.SetSizer(sizer_2)
        sizer_1.Add(self.panel_1, 0, wx.EXPAND, 0)
        sizer_3_copy.Add(self.label_1, 0, 0, 0)
        self.panel_3.SetSizer(sizer_3_copy)
        sizer_1.Add(self.panel_3, 0, wx.EXPAND, 0)
        sizer_1.Add(self.REPORTVIEWER, 1, wx.EXPAND, 0)
        self.SetSizer(sizer_1)
        self.Layout()
        # end wxGlade
        
    def loadExceptions(self,exceptions):
        for i in exceptions:
            self.REPORTVIEWER.AppendRows()
            self.REPORTVIEWER.SetCellValue(self.REPORTVIEWER.GetNumberRows()-1,0,i[0])
            self.REPORTVIEWER.SetCellValue(self.REPORTVIEWER.GetNumberRows()-1,1,i[1])
            self.REPORTVIEWER.SetCellEditor(self.REPORTVIEWER.GetNumberRows()-1,2,exception_types)
            self.REPORTVIEWER.SetCellValue(self.REPORTVIEWER.GetNumberRows()-1,2,i[2])
        self.REPORTVIEWER.AppendRows()
        self.REPORTVIEWER.SetCellEditor(self.REPORTVIEWER.GetNumberRows()-1,2,exception_types)
        self.REPORTVIEWER.AutoSizeColumns()

    def setInput(self, event):  # wxGlade: MyFrame.<event_handler>
        dia = wx.FileDialog(None,message = "Open File", wildcard = "CSV Files (*.csv; *.CSV)|*.csv;*.CSV|" "All files (*.*)|*.*", style = wx.OPEN | wx.MULTIPLE)
        if dia.ShowModal() == wx.ID_OK:
            filepaths = dia.GetPaths()
            for i in filepaths:
                if ":" not in i:
                    wx.MessageBox("UNC Paths not supported.  Please use your drives","ERROR",wx.ICON_ERROR)
                    event.Skip()
                    return
            self.input_files = filepaths
            self.INPUTPATH.Label = ", ".join(filepaths)
        event.Skip()

    def setOutput(self, event):  # wxGlade: MyFrame.<event_handler>
        dia = wx.FileDialog(None,message = "Save File", wildcard = "MS Import Files (*.dta; *.DTA)|*.dta;*.DTA|" "All files (*.*)|*.*", style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
        if dia.ShowModal() == wx.ID_OK:
            filepath = dia.GetPaths()[0]
            if ":" not in filepath:
                wx.MessageBox("UNC Paths not supported.  Please use your drives","ERROR",wx.ICON_ERROR)
                event.Skip()
                return
            self.OUTPUTPATH.Label = filepath
            self.db["OUTPUTPATH"] = filepath
            o=open('./settings.txt','w')
            o.write(json.dumps(self.db))
            o.close()
        event.Skip()

    def processFile(self, event):  # wxGlade: MyFrame.<event_handler>
        if self.PERIOD.Value == "":
            wx.MessageBox("Please Select A Period to Post","ERROR",wx.ICON_ERROR)
            return
        if not self.input_files:
            wx.MessageBox("Please Select file(s) to process","ERROR",wx.ICON_ERROR)
            return
        if self.OUTPUTPATH.Label == "":
            wx.MessageBox("Please an Output File","ERROR",wx.ICON_ERROR)
            return
        if self.LOGPATH.Label == "":
            wx.MessageBox("Please a Log File","ERROR",wx.ICON_ERROR)
            return
        log = ""
        
        o=open(self.OUTPUTPATH.Label,'w')
        o.close()
        
        o = open(self.OUTPUTPATH.Label.split(".")[0]+"-gltransactions.dta","w")
        o.close()
        
        invoices = {}
        notices = {}
        gltrans = {}
        batches = {}
        expenses = {}
        reimbursements = []
        
        output = ""
        
        header = "Batch,,{},{},{}\n"
        document = "Document,,{},{},,{},,,{},,{},\n"
        transaction = "Transaction,Invoice,{},,,{},,,{},,,{}\n"
        
        gl_header = "Batch,,,,{},{},,,,,{}\n"
        gl_detail = "Detail,{},{},{},,,{},{},{},,\n"
        
        exception_switch = {"":invoices,
            "GL Journal Entry":gltrans,
            "Separate Batch":batches,
        }
        exception_dict = {}
        for i in self.exceptions:
            exception_dict[i[0]] = i

        for input_file in self.input_files:

            i = open(input_file,'r')
            lines = csv.reader(StringIO.StringIO(i.read()),MyDialect())
            i.close()
            
            for i in lines:
                if i[1] == "Batch Date":
                    continue
                if i[0] == "Invoice":
                    doc_type = "VO"
                    vend_name = i[2]
                    vend_code = i[3].replace(",","")
                    vend_invcnbr = i[4].replace(",","")
                    invc_date = i[5].split("-")
                    invc_date = "{}/{}/{}".format(invc_date[1],invc_date[2],invc_date[0])
                    invc_amt = i[6]
                    if float(invc_amt)<0:
                        invc_amt = str(float(invc_amt)*-1)
                        doc_type = "AD"
                    gl_code = i[8]
                    desc = i[10].replace(",","")
                    line_tot = i[12]
                    if doc_type == "AD":
                        line_tot = str(float(line_tot)*-1)
                    dept = i[15]
                    sub_dept = i[16]
                    proj = i[17]
                    special = i[18]
                    shipping = float(i[19])
                    tax = float(i[20])
                    request_id = i[21]


                    target_exception = exception_dict.get(vend_name,["","",""])
                    target_type = exception_switch.get(target_exception[2],invoices)
                    vend_code = target_exception[1] or vend_code

                    if proj:
                        gl_code,ID = proj.split("-")
                        desc = "{} {}".format(ID,desc)
                        sub_dept = '01-600-0'
                        
                    dept = sub_dept or dept

                    if special:
                        notices[(doc_type,vend_code,vend_invcnbr,invc_date,invc_amt,request_id)] = notices.get((doc_type,vend_code,vend_invcnbr,invc_date,invc_amt,request_id),special)
                    
                    if tax or shipping:
                        tax_shipping = tax+shipping
                        ratio = float(line_tot)/(float(invc_amt)-tax_shipping)
                        line_tot = format(float(line_tot)+ratio*tax_shipping,'.2f')
                    

                
                    target_type[(doc_type,vend_code,vend_invcnbr,invc_date,invc_amt,request_id)] = target_type.get((doc_type,vend_code,vend_invcnbr,invc_date,invc_amt,request_id),[])
                    target_type[(doc_type,vend_code,vend_invcnbr,invc_date,invc_amt,request_id)].append([gl_code,dept.replace("-",""),desc,line_tot])
                if i[0] == "Expense":
                    doc_type = "VO"
                    vend_code = i[2]
                    cc = i[3]
                    dept = i[4]
                    employee = '{} {}'.format(i[5],i[6])
                    if vend_code == "0000":
                        vend_code = "{}{}".format(i[6],i[5]).upper()

                    gl_code = i[7]
                    amt = i[8]
                    drcr = i[9]
                    proj = i[10]
                    sub_dept = i[11]
                    desc = "{} {} {}".format(cc,i[13],i[12])
                    report_id = i[14]
                    tran_date = i[15].split("-")
                    tran_date = "{}/{}/{}".format(tran_date[1],tran_date[2],tran_date[0])
                    report_amt = i[16]
                    
                    if drcr == "CR" and float(amt) < 0:
                        amt = str(float(amt)*-1)
                        doc_type = "AD"
                        report_amt = amt

                    if proj:
                        desc = "{} {} {} {}".format(cc,proj,i[13],i[12])
                        gl_code,ID = proj.split("-")
                        sub_dept = "01-600-0"
                    
                    if " - Personal" in vend_code:
                        vend_code = vend_code.split(" - ")[0]
                        gl_code = "1140"
                        sub_dept = "01-600-0"
                        desc = "{} {}".format(employee,i[13])

                    dept = sub_dept or dept
                    

                    expenses[(doc_type,vend_code,cc,tran_date,report_amt,report_id)] = expenses.get((doc_type,vend_code,cc,tran_date,report_amt,report_id),[])
                    expenses[(doc_type,vend_code,cc,tran_date,report_amt,report_id)].append([gl_code,dept.replace("-",""),desc,amt])
        
        for doc,trans in expenses.iteritems():
            total = 0.0
            for tran in trans:
                total += float(tran[3])
            vend_code = doc[1]
            target_exception = exception_dict.get(vend_code,["","",""])
            target_type = exception_switch.get(target_exception[2],invoices)
            vend_code = target_exception[1] or vend_code
            target_type[(doc[0],vend_code,doc[2],doc[3],total,doc[5])] = trans
            
                    
                    
        batch_total = 0.0
        for doc,trans in invoices.iteritems():
            batch_total += float(doc[4])
            output += document.format(*doc[:-1])
            for tran in trans:
                output += transaction.format(*tran)
        if invoices:
            output = header.format(str(self.YEAR.Value)+format(int(self.PERIOD.Value),'02d'),{"Hold":"H","Release Now":"R"}[self.HANDLING.Value],"{:.2f}".format(batch_total)) + output
        
        for doc,trans in batches.iteritems():
            output += header.format(str(self.YEAR.Value)+format(int(self.PERIOD.Value),'02d'),{"Hold":"H","Release Now":"R"}[self.HANDLING.Value],"{:.2f}".format(float(doc[4])))
            output += document.format(*doc[:-1])
            for tran in trans:
                output += transaction.format(*tran)
        if output:
            o = open(self.OUTPUTPATH.Label,"w")
            o.write(output)
            o.close()
        else:
            os.remove(self.OUTPUTPATH.Label)
        
        if gltrans:
            batch_total = 0.0
            output = ""
            dlg = wx.TextEntryDialog(None, "GL Transaction Reference Number", defaultValue=self.db["GLREF"])
            dlg.ShowModal()
            refnbr = dlg.GetValue()
            dlg.Destroy()
            self.db["GLREF"] = refnbr
            dlg = wx.TextEntryDialog(None, "Clearing Acct Number", defaultValue=self.db["CLEARINGACCT"])
            dlg.ShowModal()
            acctnbr = dlg.GetValue()
            self.db["CLEARINGACCT"] = acctnbr
            
            dlg.Destroy()
            dlg = wx.TextEntryDialog(None, "Clearing Sub-Acct Number", defaultValue=self.db["CLEARINGSUBACCT"])
            dlg.ShowModal()
            subacctnbr = dlg.GetValue().replace("-","")
            dlg.Destroy()
            self.db["CLEARINGSUBACCT"] = subacctnbr
            
            o=open('./settings.txt','w')
            o.write(json.dumps(self.db))
            o.close()
            for doc,trans in gltrans.iteritems():
                batch_total += float(doc[4])
                for tran in trans:
                    output += gl_detail.format(tran[0],tran[1],refnbr,tran[3],"0.00",tran[2])
            output = gl_detail.format(acctnbr,subacctnbr,refnbr,"0.00","{:.2f}".format(batch_total),"Summary by account") + output
            output = gl_header.format(str(self.YEAR.Value)+format(int(self.PERIOD.Value),'02d'),{"Hold":"H","Release Now":"R"}[self.HANDLING.Value],"{:.2f}".format(batch_total)) + output
            o = open(self.OUTPUTPATH.Label.split(".")[0]+"-gltransactions.dta","w")
            o.write(output)
            o.close()
        else:
            os.remove(self.OUTPUTPATH.Label.split(".")[0]+"-gltransactions.dta")
        wx.MessageBox("Done","Info",wx.ICON_INFORMATION)
        
        for doc,message in notices.iteritems():
            log += "Check for {} handling notes: {}\n".format(doc[0],message)
        
        for i in reimbursements:
            log += "Reimbursement detected for {}, {} ({})\n".format(*i)

        o = open(self.LOGPATH.Label,"w")
        o.write(log)
        o.close()
        
        if log:
            os.system("start notepad {} &".format(self.LOGPATH.Label))
        
        event.Skip()

    def saveReport(self, event):  # wxGlade: MyFrame.<event_handler>
        if self.save_exceptions:
            mylist = []
            for i in range(self.REPORTVIEWER.GetNumberRows()):
                if self.REPORTVIEWER.GetCellValue(i,0) != '':
                    mylist.append([self.REPORTVIEWER.GetCellValue(i,0),self.REPORTVIEWER.GetCellValue(i,1),self.REPORTVIEWER.GetCellValue(i,2)])
                    if i+1 == self.REPORTVIEWER.GetNumberRows():
                        self.REPORTVIEWER.AppendRows()
                        self.REPORTVIEWER.SetCellEditor(self.REPORTVIEWER.GetNumberRows()-1,1,exception_types)
            self.save_exceptions = False
            self.REPORTVIEWER.AutoSizeColumns()
            self.save_exceptions = True
            self.db["EXCEPTIONS"] = mylist
            self.exceptions = mylist
            o=open('./settings.txt','w')
            o.write(json.dumps(self.db))
            o.close()
            self.save_exceptions = False
            self.REPORTVIEWER.AutoSizeColumns()
            self.save_exceptions = True
            event.Skip()
        
        
    def validatePTP(self, event):  # wxGlade: MyFrame.<event_handler>
        current_month = datetime.datetime.now()
        if datetime.datetime.strptime(str(self.PERIOD.Value), '%m/%d/%y %H:%M:%S') > current_month:
            wx.MessageBox(message,'Exporter set to future month',"Warning",wx.ICON_WARNING)
        event.Skip()
        
    def saveYear(self, event):  # wxGlade: MyFrame.<event_handler>
        if self.save_year:
            self.db['YEAR'] = self.YEAR.Value
            o=open('./settings.txt','w')
            o.write(json.dumps(self.db))
            o.close()
        event.Skip()
        
    def setLog(self, event):  # wxGlade: MyFrame.<event_handler>
        dia = wx.FileDialog(None,message = "Save File", wildcard = "Log Files (*.txt; *.TXT)|*.txt;*.TXT|" "All files (*.*)|*.*", style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
        if dia.ShowModal() == wx.ID_OK:
            filepath = dia.GetPaths()[0]
            if ":" not in filepath:
                wx.MessageBox("UNC Paths not supported.  Please use your drives","ERROR",wx.ICON_ERROR)
                event.Skip()
                return
            self.LOGPATH.Label = filepath
            self.db["LOGPATH"] = filepath
            o=open('./settings.txt','w')
            o.write(json.dumps(self.db))
            o.close()
        event.Skip()
# end of class MyFrame

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, wx.ID_ANY, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()
