def __init__(self, api_key: str, api_path: str, move_from: str, move_to: str, age: int): """ Move Issues Init :param api_key: The api key for auth user :param api_path: Path to the api :param move_from: ID string of project to move tasks from :param move_to: ID string of project to move tasks from :param age: Find issues with an actual completion date greater than this value in months. """ self.api_key = api_key self.api_path = api_path self.move_from = move_from self.move_to = move_to self.age = age # Can't bluk move more than 100 elements as per API restrictions self.max_results = 100 self.completion_date_str = "$$TODAY-{age}m".format(age=self.age) self.client = StreamClient(self.api_path, self.api_key)
def example(): client = StreamClient('http://localhost:8080/attask/api') print 'Logging in...' client.login('admin', 'user') print 'Done' print 'Retrieving user...' user = AtTaskObject( client.get(ObjCode.USER, client.user_id, ['ID', 'homeGroupID', 'emailAddr'])) print 'Done' print user print 'Searching projects...' results = client.search(ObjCode.PROJECT, {'groupID': user.homeGroupID}) print 'Done' print '%s project(s) found' % len(results) for p in results: project = AtTaskObject(p) print ' - %s' % project.name print 'Creating project...' project = AtTaskObject( client.post(ObjCode.PROJECT, { 'name': 'My Project', 'groupID': user.homeGroupID })) print 'Done' print project print 'Retrieving project...' project = AtTaskObject(client.get(ObjCode.PROJECT, project.ID)) print 'Done' print project print 'Editing project...' project = AtTaskObject( client.put(ObjCode.PROJECT, project.ID, {'ownerID': user.ID}), client) print 'Done' print project print 'Deleting project...' client.delete(ObjCode.PROJECT, project.ID) print 'Done' print 'Creating another project...' project = AtTaskObject({}, client) project.objCode = ObjCode.PROJECT project.name = 'My New Project' project.groupID = user.homeGroupID project.save() print 'Done' print project print 'Editing another project...' project.ownerID = user.ID project.save() print 'Done' print project print 'Deleting another project...' client.delete(ObjCode.PROJECT, project.ID) print 'Done' print 'Logging out...' client.logout() print 'Done'
item['projID'] + ' | ' + item['projName'] + '\n') templistforemail.append( str(datetime.now().strftime("%Y-%m-%d %H:%M")) + ' | ' + item['projID'] + ' | ' + item['projName'] + '\n') # Sends email to each person in email list names = ['*****@*****.**', '*****@*****.**'] for name in names: mailsend.sendmail(''.join(templistforemail), name) outFile.close() # Because it is awesome and we can def wizardCall(): with open('wizard.txt', 'r') as fin: print fin.read() fin.close() ################################################################################ # Main() if __name__ == '__main__': wizardCall() username = '******' password = '******' #an actual password has would go here client = StreamClient('https://somedomain.attask-ondemand.com/attask/api/') client.login(username, masking.unmask(password)) getProject() updateProjectPCD() writeToFile(projIDlist)
CATEGORY_BACKLOG_ITEM = '4c78aaa7000c4bc23722d1bebdf9d77f' class TShirtSize: SMALL = 5 MEDIUM = 10 LARGE = 15 #get the command line parameters and make sense of them parser = argparse.ArgumentParser(description='Issue To Task') parser.add_argument('issueID', action='store', type=str, help="This is the issue GUID on dot8") parser.add_argument('-b', action='store_true', default=False, dest='isBlocking', help='Whether to set it as a blocking task') parser.add_argument('-p', nargs="?", dest='points', default=0, type=int, required=False, help='How many points the task is worth') args = parser.parse_args() #we will refer to this object later to key off the properties set on it connection = StreamClient(API_URL) try: connection.login(USERNAME,PASSWORD) except Exception, e: print "Error connecting to %s" % connection.url print e exit(0) def printProject(project): print "%s [Project]" % project['name'] tasks = sorted(project['tasks'],key=lambda k: k['taskNumber']) for task in tasks: if task['parentID'] is None: #parent task print "\tTask %d: %s" % (task['taskNumber'],task['name']) line()
from Tkinter import * #Global Variables username = '******' password = '******' carrieridlist = 'carrieridlist' periodid = '0' taskname = 'taskname' Builder = 'Builder' projIDlist = [] taskIDlist = [] assignIDlist = [] #this will need to be updated with the actual subdomain to be valid #also 'CoName' needs to be find and replaced with the company name client = StreamClient( 'https://entersubdomainhere.attask-ondemand.com/attask/api/') #start TKinter build# root = Tk() root.resizable(width=False, height=False) mainframe = Frame(root) mainframe.pack() photo = PhotoImage(file="broadsword.gif") test = Label(mainframe, image=photo, bd=5) test.image = photo test.grid(column=0, row=0, columnspan=2) unL = Label(mainframe, text='Batch edit WF assignments | Written by BE') unL.grid(column=0, row=1, columnspan=2)
from api import StreamClient, ObjCode from local_credentials import API_URL, USERNAME, PASSWORD PROJECT_ID = "50047866000005b833d7a1da52e5f69c" connection = StreamClient(API_URL) try: connection.login(USERNAME,PASSWORD) except Exception, e: print "Error connecting to %s" % connection.url print e exit(0) def createTask(name): result = connection.post(ObjCode.TASK,{'name': name, 'projectID':PROJECT_ID}) project = connection.get(ObjCode.PROJECT,PROJECT_ID,['tasks:*']) #AtTaskObject(connection.get(ObjCode.PROJECT,PROJECT_ID,['tasks:*']), connection) print "%s [Project]" % project['name'] for task in project['tasks']: print "\tTask %d: %s" % (task['taskNumber'],task['name']) createTask("bobbo's Task!!")
class MoveIssues(object): def __init__(self, api_key: str, api_path: str, move_from: str, move_to: str, age: int): """ Move Issues Init :param api_key: The api key for auth user :param api_path: Path to the api :param move_from: ID string of project to move tasks from :param move_to: ID string of project to move tasks from :param age: Find issues with an actual completion date greater than this value in months. """ self.api_key = api_key self.api_path = api_path self.move_from = move_from self.move_to = move_to self.age = age # Can't bluk move more than 100 elements as per API restrictions self.max_results = 100 self.completion_date_str = "$$TODAY-{age}m".format(age=self.age) self.client = StreamClient(self.api_path, self.api_key) def go(self): """ Starts the moving process. """ results_len = 1 # Just something to get us started while results_len > 0: issues = self.find_issues() results_len = len(issues) iss_move_count = self.move_issues(issues) if results_len > 0: results_str = "Moved {result_count} items".format(result_count=iss_move_count) print(results_str) print("Operation complete") def find_issues(self): """ Finds issues in 'from' project to be moved. :return: a list of issues that meet the criteria """ params = { "$$LIMIT": self.max_results, "projectID": self.move_from, "projectID_Mod": "in", "actualCompletionDate": self.completion_date_str, "actualCompletionDate_Mod": "lte" } fields = {} results = AtTaskObject(self.client.search(ObjCode.ISSUE, params, fields)) return results.data def move_issues(self, data) -> int: """ Moves issues between projects :param data: list of issues :return: count of issues moved """ counter = 0 for item in data: # Get the ID number uid = item['ID'] params = {'projectID': self.move_to} AtTaskObject(self.client.action(ObjCode.ISSUE, 'move', params, objid=uid)) print(".", end="", flush=True) counter += 1 return counter def get_proj_name(self, proj_id: str): """ Gets the name of a project from ID :param proj_id: ID number of the project to get the name of :return: Name of the project """ results = AtTaskObject(self.client.get(ObjCode.PROJECT, proj_id)) return results.data['name'] def get_number_of_issues_to_move(self): """ Get's a count of the number of issues to be moved :return: a count of the number of issues to be moved """ params = { "projectID": self.move_from, "projectID_Mod": "in", "actualCompletionDate": self.completion_date_str, "actualCompletionDate_Mod": "lte" } results = AtTaskObject(self.client.report(ObjCode.ISSUE, params, 'sum')) return results.data['dcount_ID']
def do_GET(self): def do_FAIL(): self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write("<!DOCTYPE html>\n") self.wfile.write("<html>\n") self.wfile.write("<head>\n") self.wfile.write("\t<meta>\n") self.wfile.write("\t<title>Fail</title>\n") self.wfile.write("\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n") self.wfile.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"http://some.linux.server/css/bootstrap.min.css\">\n") self.wfile.write("</head>\n") self.wfile.write("<body>\n") self.wfile.write("\t<script src=\"http://code.jquery.com/jquery.min.js\"></script>\n") self.wfile.write("\t<script src=\"http://some.linux.server/js/bootstrap.min.js\"></script>\n") self.wfile.write("\n\t<div class=\"container\">\n") self.wfile.write("\n\t<h1>Sorry :(</h1>\n") self.wfile.write("\n\tThere's nothing to see here.\n") self.wfile.write("</body>\n") self.wfile.write("</html>\n") return # log the thread id message = threading.currentThread().getName() # parse the URL parsed_path = urlparse.urlparse(self.path) params = urlparse.parse_qs(parsed_path.query) # print params # authenticate to Workfront API client = StreamClient('https://DOMAIN.attask-ondemand.com/attask/api') client.login('ADMINUSERNAME','PASSWORD') # get the object type from the parameters objectTypeParam = params['type'] # print objectTypeParam[0] thisObjectCode = params['object'] if (objectTypeParam[0] == 'TASK'): try: thisObject = AtTaskObject(client.get(ObjCode.TASK,thisObjectCode[0],{'referenceNumber','DE:JIRA'})) keyFieldQuote = 'qd.Character02' # QuoteDtl.Character02 is used for JIRA Link (Workfront Link) keyFieldOrder = 'od.Character02' # OrderDtl.Character02 is used for JIRA Link (Workfront Link) keyFieldJob = 'od.Character02' # JobHead.Character02 is used for JIRA Link (Workfront Link) keyFieldInvoice = 'od.Character02' # JobHead.Character02 is used for JIRA Link (Workfront Link) except: do_FAIL() return elif (objectTypeParam[0] == 'ISSUE'): try: thisObject = AtTaskObject(client.get(ObjCode.ISSUE,thisObjectCode[0],{'referenceNumber','DE:JIRA'})) keyFieldQuote = 'qd.Character02' # QuoteDtl.Character02 is used for JIRA Link (Workfront Link) keyFieldOrder = 'od.Character02' # OrderDtl.Character02 is used for JIRA Link (Workfront Link) keyFieldJob = 'od.Character02' # OrderDtl.Character02 is used for JIRA Link (Workfront Link) keyFieldInvoice = 'od.Character02' # OrderDtl.Character02 is used for JIRA Link (Workfront Link) except: do_FAIL() return elif (objectTypeParam[0] == 'PROJ'): try: thisObject = AtTaskObject(client.get(ObjCode.PROJECT,thisObjectCode[0],{'referenceNumber','DE:JIRA','DE:Epicor Code'})) keyFieldQuote = 'qh.ShortChar05' # QuoteHed.ShortChar05 is used for Project Code keyFieldOrder = 'oh.ShortChar05' # OrderHed.ShortChar05 is used for Project Code keyFieldJob = 'jh.ShortChar05' # JobHead.ShortChar05 is used for ProjectCode keyFieldInvoice = 'oh.ShortChar05' # OrderHed.ShortChar05 is used for ProjectCode except: do_FAIL() return else: do_FAIL() return # get the object code from the URL parser, and create an AtTask object for the related task # print thisObject # get the object type, referenceNumber, and JIRA code for the task objectType = thisObject.data.get('objCode') refNum = thisObject.referenceNumber jiraCode = thisObject.data.get('DE:JIRA','none') projectCode = thisObject.data.get('DE:Epicor Code','none') # print objectType # print refNum # print jiraCode # print projectCode # manage Epicor link transition from JIRA code to Workfront referenceNum # if the JIRA custom field is present, use its contents as the idCode # otherwise, use the referenceNumber if '-' in jiraCode: idCode = jiraCode else: idCode = refNum # if we're looking for a project, search on the Project Code, not the JIRA code / Workfront ID if (objectType == 'PROJ'): idCode = projectCode # if there is no project code defined, idCode will be set to 'none', so trap for that if (idCode == 'none'): do_FAIL() return # connect to MS SQL server conn = _mssql.connect(server='MSSQLSERVER.domain.tld',user='******',password='******',database='Epicor905') # string containing SQL query for Quote details quoteSQL = """ SELECT LEFT(qh.ShortChar05, 5) AS ProjID, qd.ProdCode, qh.DateQuoted, (CAST(qd.QuoteNum AS varchar) + ' / ' + CAST(qd.QuoteLine AS varchar)) AS QuoteLine, (CAST(qd.SellingExpectedQty AS int)) AS Qty, (CAST(qd.DocExtPriceDtl AS money)) AS LineCharges, (CAST(ISNULL(aggregateMisc.MiscTotal, 0) AS money)) AS MiscCharges, (CAST((ISNULL(SUM(aggregateMisc.MiscTotal), 0) + qd.DocExtPriceDtl) AS money)) AS Total, (CAST(qd.PartNum AS varchar) + ' / ' + LEFT(CAST(qd.LineDesc AS varchar),50) ) AS PNDesc FROM Epicor905.dbo.QuoteDtl AS qd LEFT OUTER JOIN Epicor905.dbo.QuoteHed AS qh ON qd.QuoteNum = qh.QuoteNum LEFT OUTER JOIN (SELECT SUM(qm.DocMiscAmt) AS MiscTotal, QuoteNum, QuoteLine FROM Epicor905.dbo.QuoteMsc AS qm GROUP BY QuoteNum, QuoteLine) AS aggregateMisc ON (qd.QuoteNum = aggregateMisc.QuoteNum) AND (qd.QuoteLine = aggregateMisc.QuoteLine) WHERE (%s LIKE \'%s%%\') GROUP BY qd.QuoteNum, qd.QuoteLine, qd.SellingExpectedQty, qd.DocExtPriceDtl, aggregateMisc.MiscTotal, qh.ShortChar05, qd.ProdCode, qh.DateQuoted, qd.PartNum, qd.LineDesc ORDER BY qd.QuoteNum DESC, qd.QuoteLine ASC """ % (keyFieldQuote, idCode) # string containing SQL query for Order details orderSQL =""" SELECT oh.OrderDate, (CAST(od.OrderNum AS varchar) + ' / ' + CAST(od.OrderLine AS varchar) + ' / ' + oh.PONum) AS OrderLinePO, (CAST(od.OrderQty AS int)) AS Qty, (CAST(od.DocExtPriceDtl AS money)) AS LineCharges, (CAST(ISNULL(aggregateMisc.MiscTotal, 0) AS money)) AS MiscCharges, (CAST((ISNULL(SUM(aggregateMisc.MiscTotal), 0) + od.DocExtPriceDtl) AS money)) AS Total, (CAST(od.PartNum AS varchar) + ' / ' + LEFT(CAST(od.LineDesc AS varchar),50) ) AS PNDesc FROM Epicor905.dbo.OrderDtl AS od LEFT OUTER JOIN (SELECT SUM(om.DocMiscAmt) AS MiscTotal, OrderNum, OrderLine FROM Epicor905.dbo.OrderMsc AS om GROUP BY OrderNum, OrderLine) AS aggregateMisc ON (od.OrderNum = aggregateMisc.OrderNum) AND (od.OrderLine = aggregateMisc.OrderLine) INNER JOIN OrderHed AS oh ON oh.Company = od.Company AND oh.OrderNum = od.OrderNum WHERE (%s LIKE \'%s%%\') GROUP BY od.OrderNum, oh.PONum, od.OrderLine, od.OrderQty, od.DocExtPriceDtl, aggregateMisc.MiscTotal, oh.OrderDate, od.PartNum, od.LineDesc ORDER BY od.OrderNum DESC, od.OrderLine ASC """ % (keyFieldOrder, idCode) # string containing SQL query for Job details jobSQL = """ SELECT jh.CreateDate, od.OrderNum, jh.JobNum, jh.ProdQty, jh.QtyCompleted, jh.DueDate, jh.JobCompletionDate, (CAST(od.PartNum AS varchar) + ' / ' + LEFT(CAST(od.LineDesc AS varchar),50) ) AS PNDesc FROM Epicor905.dbo.OrderDtl AS od INNER JOIN Epicor905.dbo.JobProd AS jp ON od.Company = jp.Company AND od.OrderNum = jp.OrderNum AND od.OrderLine = jp.OrderLine INNER JOIN Epicor905.dbo.JobHead AS jh ON jp.Company = jh.Company AND jp.JobNum = jh.JobNum WHERE UPPER(%s) LIKE \'%s\' AND jh.JobReleased = 1 ORDER BY jh.CreateDate DESC """ % (keyFieldJob, idCode) # string containing SQL query for Invoice details invoiceSQL = """ SELECT InvoiceNum, InvoiceDate, DocInvoiceAmt, OpenInvoice, OrderNum, PONum FROM Epicor905.dbo.InvcHead ih WHERE ih.OrderNum IN (SELECT DISTINCT od.ORDERNUM FROM Epicor905.dbo.OrderDtl od LEFT OUTER JOIN Epicor905.dbo.OrderHed oh ON od.Company = oh.Company AND od.OrderNum = oh.OrderNum WHERE %s LIKE \'%s\') ORDER BY ih.InvoiceDate DESC """ % (keyFieldInvoice, idCode) # send HTTP 200 OK status code, headers self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() # write HTML top matter self.wfile.write("<!DOCTYPE html>\n") self.wfile.write("<html>\n") self.wfile.write("<head>\n") self.wfile.write("\t<meta>\n") self.wfile.write("\t<title>Epicor Integration</title>\n") self.wfile.write("\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n") self.wfile.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"http://some.linux.server/css/bootstrap.min.css\">\n") self.wfile.write("</head>\n") self.wfile.write("<body>\n") self.wfile.write("\t<script src=\"http://code.jquery.com/jquery.min.js\"></script>\n") self.wfile.write("\t<script src=\"http://some.linux.server/js/bootstrap.min.js\"></script>\n") self.wfile.write("\n\t<div class=\"container\">\n") if (objectType == 'PROJ'): self.wfile.write("\n\t<h2>Epicor Reports for Project {0}</h2>\n".format(idCode)) self.wfile.write("\n\t<p>In Workfront, the Project Code is selected in \ Project Details > Standard Project Form > Epicor Code. In Epicor, the Project code is \ selected from the dropdown menu on Epicor Quotes, Orders, and Jobs. This report shows Epicor\ details matching the selected Project Code. Click on each panel to display details.</p>\n") else: self.wfile.write("\n\t<h2>Epicor Reports for Task {0}</h2>\n".format(idCode)) self.wfile.write("\n\t<p>This report provides details related to the Task ID that is entered in the \ \"JIRA Link\" field on Epicor quotes and orders. For old entries, the Task ID is the \ JIRA code (\"PROTO-123\"). For new entries, the Task ID is the Workfront Task Reference Number \ (\"12345\"). Click on each panel to hide details.</p>\n") self.wfile.write("\n\t\t<div class=\"panel-group\" id=\"accordian\">\n") # execute SQL query for quote detail conn.execute_query(quoteSQL) # create an empty list for rows of strings to be joined later tempList = [] # create table for quote details self.wfile.write("\n\t\t\t<div class=\"panel panel-primary\">\n") self.wfile.write("\n\t\t\t\t<div class=\"panel panel-heading\">\n") self.wfile.write("\t\t\t\t\t<h3 class=\"panel-title\">\n") self.wfile.write("\t\t\t\t\t\t<a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#accordionOne\">\n") self.wfile.write("\t\t\t\t\t\t\tQuote Details\n") self.wfile.write("\t\t\t\t\t\t</a>\n") self.wfile.write("\t\t\t\t\t</h3>\n") self.wfile.write("\t\t\t\t</div> <!-- close panel-heading -->\n") # for PROJ reports, there's usually lots of data, so start with the panels collapsed # for TASK/ISSUE reports, there is usually less data, so start with the panels expanded if (objectType == 'PROJ'): self.wfile.write("\n\t\t\t\t<div id=\"accordionOne\" class=\"panel-collapse collapse\">\n") else: self.wfile.write("\n\t\t\t\t<div id=\"accordionOne\" class=\"panel-collapse collapse in\">\n") self.wfile.write("\t\t\t\t\t<div class=\"panel-body\">\n") self.wfile.write("\t\t\t\t\t\t<table class=\"table table-striped\">\n") tempList.append('\t\t\t\t\t\t\t<tr><thead>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Date Quoted</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Quote / Line</th>\n') # tempList.append('\t\t\t\t\t\t\t\t<th>Project Code</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>PN / Description</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Product Group</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Quantity</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Line Charges</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Misc Charges</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Total Value</th>\n') tempList.append('\t\t\t\t\t\t\t</tr></thead>\n') for row in conn: tempList.append('\t\t\t\t\t\t\t\t<tr>\n') try: dateString = (row['DateQuoted']).strftime('%d %b %Y') except: # dateString = str(None) did this cause a problem? dateString = 'None' tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-left\">', dateString, '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', row['QuoteLine'], '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', row['PNDesc'], '</td>\n')) # tempList.extend(('\t\t\t\t\t\t\t\t<td>', row['ProjID'], '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', row['ProdCode'], '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['Qty']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['LineCharges']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['MiscCharges']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['Total']), '</td>\n')) tempList.append('\t\t\t\t\t\t\t\t</tr>\n') tempList.append('\t\t\t\t\t\t</table>\n') tempList.append('\t\t\t\t\t</div> <!-- close panel body -->\n') tempList.append('\t\t\t\t</div> <!-- close accordianOne -->\n') tempList.append('\t\t\t</div> <!-- close panel-primary -->\n') # join rows of list into a new strting, and write it to the page quoteString = ''.join(tempList).encode('utf-8') try: self.wfile.write(quoteString) except: self.wfile.write('sorry, i choked on something i found in the list of quotes\n') self.wfile.write("\t\t\t<p></p>\n") #repeat to order details conn.execute_query(orderSQL) tempList = [] self.wfile.write("\n\t\t\t<div class=\"panel panel-primary\">\n") self.wfile.write("\n\t\t\t\t<div class=\"panel panel-heading\">\n") self.wfile.write("\t\t\t\t\t<h3 class=\"panel-title\">\n") # for PROJ reports, there's usually lots of data, so start with the panels collapsed # for TASK/ISSUE reports, there is usually less data, so start with the panels expanded self.wfile.write("\t\t\t\t\t\t<a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#accordionTwo\">\n") self.wfile.write("\t\t\t\t\t\t\tOrder Details\n") self.wfile.write("\t\t\t\t\t\t</a>\n") self.wfile.write("\t\t\t\t\t</h3>\n") self.wfile.write("\t\t\t\t</div> <!-- close panel-heading -->\n") if (objectType == 'PROJ'): self.wfile.write("\n\t\t\t\t<div id=\"accordionTwo\" class=\"panel-collapse collapse\">\n") else: self.wfile.write("\n\t\t\t\t<div id=\"accordionTwo\" class=\"panel-collapse collapse in\">\n") self.wfile.write("\t\t\t\t\t<div class=\"panel-body\">\n") self.wfile.write("\t\t\t\t\t\t<table class=\"table table-striped\">\n") tempList.append('\t\t\t\t\t\t\t<tr><thead>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Order Date\n') tempList.append('\t\t\t\t\t\t\t\t<th>SO / Line / PO</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>PN / Description</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Quantity</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Line Charges</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Misc Charges</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Total Value</th>\n') tempList.append('\t\t\t\t\t\t\t</tr></thead>\n') for row in conn: tempList.append('\t\t\t\t\t\t\t<tr>\n') try: dateString = (row['OrderDate']).strftime('%d %b %Y') except: dateString = str(None) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-left\">', dateString, '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', row['OrderLinePO'], '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', row['PNDesc'], '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['Qty']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['LineCharges']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['MiscCharges']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['Total']), '</td>\n')) tempList.append('\t\t\t\t\t\t\t</tr>\n') tempList.append('\t\t\t\t\t\t</table>\n') tempList.append('\t\t\t\t\t</div> <!-- close panel body -->\n') tempList.append('\t\t\t\t</div> <!-- close accordianTwo -->\n') tempList.append('\t\t\t</div> <!-- close panel-primary -->\n') orderString = ''.join(tempList).encode('utf-8') self.wfile.write(orderString) self.wfile.write("\t\t\t<p></p>\n") # repeat for Job details conn.execute_query(jobSQL) tempList = [] self.wfile.write("\n\t\t\t<div class=\"panel panel-primary\">\n") self.wfile.write("\n\t\t\t\t<div class=\"panel panel-heading\">\n") self.wfile.write("\t\t\t\t\t<h3 class=\"panel-title\">\n") self.wfile.write("\t\t\t\t\t\t<a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#accordionThree\">\n") self.wfile.write("\t\t\t\t\t\t\tJob Details\n") self.wfile.write("\t\t\t\t\t\t</a>\n") self.wfile.write("\t\t\t\t\t</h3>\n") self.wfile.write("\t\t\t\t</div> <!-- close panel-heading -->\n") if (objectType == 'PROJ'): self.wfile.write("\n\t\t\t\t<div id=\"accordionThree\" class=\"panel-collapse collapse\">\n") else: self.wfile.write("\n\t\t\t\t<div id=\"accordionThree\" class=\"panel-collapse collapse in\">\n") self.wfile.write("\t\t\t\t\t<div class=\"panel-body\">\n") self.wfile.write("\t\t\t\t\t\t<table class=\"table table-striped\">\n") tempList.append('\t\t\t\t\t\t\t<tr><thead>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Created</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Job Number</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>SO Number</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>PN / Description</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Start Qty</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Complete Qty</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Due Date</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Job Completion Date</th>\n') tempList.append('\t\t\t\t\t\t\t</tr></thead>\n') for row in conn: tempList.append('\t\t\t\t\t\t\t<tr>\n') try: dateString = (row['CreateDate']).strftime('%d %b %Y') except: dateString = 'None' tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-left\">', dateString, '</td>\n')) try: jobString = "%s" % row['JobNum'] jobString = jobString.encode('utf-8') except: jobString = 'Unicode' print "I just choked on a Unicode character in Job number field" print row['JobNum'] tempList.extend(('\t\t\t\t\t\t\t\t<td>', jobString, '</td>\n')) try: orderString = "%d" % row['OrderNum'] except: orderString = "Choked on Unicode" print "I just choked on a Unicode character in Order number field" tempList.extend(('\t\t\t\t\t\t\t\t<td>', orderString, '</td>\n')) try: pnString = "%s" % row['PNDesc'] except: pnString = "Choked on Unicode" print "I just choked on a Unicode character in PNDesc field" tempList.extend(('\t\t\t\t\t\t\t\t<td>', str(row['PNDesc']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['ProdQty']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['QtyCompleted']), '</td>\n')) try: dateString = (row['DueDate']).strftime('%d %b %Y') except: dateString = 'None' tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', dateString, '</td>\n')) try: dateString = (row['JobCompletionDate']).strftime('%d %b %Y') except: dateString = 'None' tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', dateString, '</td>\n')) tempList.append('\t\t\t\t\t\t\t</tr>\n') tempList.append('\t\t\t\t\t\t</table>\n') tempList.append('\t\t\t\t\t</div> <!-- close panel body -->\n') tempList.append('\t\t\t\t</div> <!-- close accordianThree -->\n') tempList.append('\t\t\t</div> <!-- close panel-primary -->\n') #newTempList = unicode(tempList, 'utf-8') #jobString = u' '.join(tempList).encode('utf-8') jobString = u' '.join(tempList).strip() self.wfile.write(jobString) self.wfile.write("\t\t\t<p></p>\n") # repeat for Invoice details conn.execute_query(invoiceSQL) tempList = [] self.wfile.write("\n\t\t\t<div class=\"panel panel-primary\">\n") self.wfile.write("\n\t\t\t\t<div class=\"panel panel-heading\">\n") self.wfile.write("\t\t\t\t\t<h3 class=\"panel-title\">\n") self.wfile.write("\t\t\t\t\t\t<a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#accordionFour\">\n") self.wfile.write("\t\t\t\t\t\t\tInvoice Details\n") self.wfile.write("\t\t\t\t\t\t</a>\n") self.wfile.write("\t\t\t\t\t</h3>\n") self.wfile.write("\t\t\t\t</div> <!-- close panel-heading -->\n") if (objectType == 'PROJ'): self.wfile.write("\n\t\t\t\t<div id=\"accordionFour\" class=\"panel-collapse collapse\">\n") else: self.wfile.write("\n\t\t\t\t<div id=\"accordionFour\" class=\"panel-collapse collapse in\">\n") self.wfile.write("\t\t\t\t\t<div class=\"panel-body\">\n") self.wfile.write("\t\t\t\t\t\t<table class=\"table table-striped\">\n") tempList.append('\t\t\t\t\t\t\t<tr><thead>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Invoice Number</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Invoice Date</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Sales Order</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th>Customer PO</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Open</th>\n') tempList.append('\t\t\t\t\t\t\t\t<th class=\"text-right\">Invoice Amount</th>\n') tempList.append('\t\t\t\t\t\t\t</tr></thead>\n') for row in conn: tempList.append('\t\t\t\t\t\t\t<tr>\n') tempList.extend(('\t\t\t\t\t\t\t\t<td>', str(row['InvoiceNum']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', (row['InvoiceDate']).strftime('%d %b %Y'), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', str(row['OrderNum']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td>', str(row['PONum']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['OpenInvoice']), '</td>\n')) tempList.extend(('\t\t\t\t\t\t\t\t<td class=\"text-right\">', "{:,.0f}".format(row['DocInvoiceAmt']), '</td>\n')) tempList.append('\t\t\t\t\t\t\t</tr>\n') tempList.append('\t\t\t\t\t\t</table>\n') tempList.append('\t\t\t\t\t</div> <!-- close panel body -->\n') tempList.append('\t\t\t\t</div> <!-- close accordianThree -->\n') tempList.append('\t\t\t</div> <!-- close panel-primary -->\n') invString = ''.join(tempList).encode('utf-8') self.wfile.write(invString) # close accordian panel group self.wfile.write("\t\t</div> <!-- close panel-group -->\n") # footnotes self.wfile.write("\n\t\t\t<h3>Footnotes</h3>\n") self.wfile.write("\t\t\t<ul>\n") self.wfile.write("\t\t\t\t<li>These data are current as of last night.</li>\n") self.wfile.write("\t\t\t\t<li>The reference number for this %s is: %s</li>\n" % (objectType, refNum) ) self.wfile.write("\t\t\t\t<li>The JIRA Link for this %s is: %s</li>\n" % (objectType, jiraCode) ) self.wfile.write("\t\t\t\t<li>The Project Code for this %s is: %s</li>\n" % (objectType, projectCode) ) self.wfile.write("\t\t\t\t<li>Quote query searched Epicor field %s for: %s</li>\n" % (keyFieldQuote, idCode) ) self.wfile.write("\t\t\t\t<li>Order query searched Epicor field %s for: %s</li>\n" % (keyFieldOrder, idCode) ) self.wfile.write("\t\t\t\t<li>Order query searched Epicor field %s for: %s</li>\n" % (keyFieldJob, idCode) ) self.wfile.write("\t\t\t\t<li>Order query searched Epicor field %s for: %s</li>\n" % (keyFieldInvoice, idCode) ) self.wfile.write("\t\t\t\t<li>Served by %s</li>\n" % message) self.wfile.write("\t\t\t</ul>\n") # close container, body, and html self.wfile.write("\n\t</div> <!-- outer container -->\n") self.wfile.write("</body>\n</html>\n") # close the MSSQL connection conn.close() return