From e03f3aae5267476a2e968c6f7bf80830e147d104 Mon Sep 17 00:00:00 2001 From: Zimmerberger Markus Date: Fri, 21 Jan 2022 17:39:39 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 1 + .vscode/launch.json | 15 ++ .vscode/settings.json | 3 + JIRA_StoryPoint_Assignee.py | 43 ++++++ JIRA_SubTasks_byComments.py | 131 ++++++++++++++++ JIRA_adapt_historical_estimations.py | 60 ++++++++ JIRA_adapt_story_points.py | 64 ++++++++ JIRA_import_ELSAP_work_log.py | 219 +++++++++++++++++++++++++++ elsap_to_jira_user.json | 25 +++ elsap_to_jira_user_old.json | 41 +++++ 10 files changed, 602 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 JIRA_StoryPoint_Assignee.py create mode 100644 JIRA_SubTasks_byComments.py create mode 100644 JIRA_adapt_historical_estimations.py create mode 100644 JIRA_adapt_story_points.py create mode 100644 JIRA_import_ELSAP_work_log.py create mode 100644 elsap_to_jira_user.json create mode 100644 elsap_to_jira_user_old.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bf0824e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.log \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..17e15f2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..fe800d2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "C:\\Python39\\python.exe" +} \ No newline at end of file diff --git a/JIRA_StoryPoint_Assignee.py b/JIRA_StoryPoint_Assignee.py new file mode 100644 index 0000000..028fe4a --- /dev/null +++ b/JIRA_StoryPoint_Assignee.py @@ -0,0 +1,43 @@ +from types import ClassMethodDescriptorType +from jira import JIRA +import csv +import xlsxwriter + +# TODO: create excel! + +host = "https://jira.wien.gv.at/" +pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" + +headers = JIRA.DEFAULT_OPTIONS["headers"].copy() +headers["Authorization"] = f"Bearer {pat}" +jira_server = JIRA(server=host, options={"headers": headers}) + +#jira_server = JIRA(basic_auth=("zim9003",""), options={'server': 'https://jira.wien.gv.at/'}) +#jira_server = JIRA(basic_auth=("postman","OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD"), options={'server': 'https://jira.wien.gv.at/'}) + +#issues_Jql = jira_server.issue('WRGWR-828',expand='changelog')#pass one issue at the time +assignees = ["thh9001","krp9002","reu9001","und9001","krj0003","bln9001","ce39001","rab9001"] +for assignee in assignees: + issues_Jql = jira_server.search_issues('sprint = 1137 AND assignee = {} ORDER BY cf[10022] ASC'.format(assignee)) #, expand='changelog') # 1093 + + xsp = lambda s: s or 0 + sp_sum = 0 + for issue in issues_Jql: + sp = 0 + if hasattr(issue.fields, 'customfield_10022'): + sp = xsp(issue.fields.customfield_10022) + sp_sum += sp + + print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp)) + + print('Summe {}: {}'.format(assignee, sp_sum)) + +#print(issues_Jql) +# changelog = issues_Jql. +# count = 0 +# for history in changelog.histories: +# for item in history.items: +# if item.field == 'status': +# if item.toString == "Reopened": +# count = count + 1 +# print(count) \ No newline at end of file diff --git a/JIRA_SubTasks_byComments.py b/JIRA_SubTasks_byComments.py new file mode 100644 index 0000000..86df003 --- /dev/null +++ b/JIRA_SubTasks_byComments.py @@ -0,0 +1,131 @@ +# find comments with estimations out of pre-planning +# zisco 2021-09-30 19:50 + +from types import ClassMethodDescriptorType +from jira import JIRA, Issue, Comment, exceptions +import re +import csv +import xlsxwriter +import logging + +def get_assignee(type): + if type == 'Dev Backend': + return 'rab9001' + elif type == 'Dev Frontend': + return 'reu9001' + elif type[:14] == 'Test-Anpassung': + return 'ada9001' + +def create_subtask(issue, parent, type, subtask_sp): + escaped = issue.fields.summary.replace('"','\\"') + print('summary ~ \"{}\"'.format(escaped)) + + subtask = jira_server.search_issues('summary ~ \"{} {}\"'.format(type, escaped)) + if len(subtask) == 0: + #right = (comment_line.find(':')+2)-len(comment_line) + #subtask_sp = float(comment_line[right:]) + assignee = get_assignee(type) + issue_dict = { + 'project': {'id': 12501}, + 'summary': "[{}] {}".format(type, escaped), + 'description': issue.fields.description, + 'issuetype': {'name': 'Sub-task'}, + 'parent': {'key': parent}, + # todo - json + #'components': [{'name': issue.fields.components}], + #'labels': [{'name': issue.fields.labels}], + 'timetracking': {'originalEstimate': "{}d".format(subtask_sp)}, + 'assignee': {'name': assignee} + } + new_issue = jira_server.create_issue(fields=issue_dict) + + # consider components + existingComponents = [] + for component in issue.fields.components: + existingComponents.append({"name" : component.name}) + new_issue.update(fields={"components": existingComponents}) + + logging.info('Created Sub-Task {}'.format(new_issue)) + else: + logging.info('Skip creating Sub-Task {} for {} as it already exists'.format(type, issue)) + +logging.basicConfig(filename='sub_task_generator.log', + filemode='a', + format='%(asctime)s - %(levelname)s: %(message)s', + level=logging.INFO, + encoding='utf-8') + +host = "https://jira.wien.gv.at/" +pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" + +headers = JIRA.DEFAULT_OPTIONS["headers"].copy() +headers["Authorization"] = f"Bearer {pat}" +jira_server = JIRA(server=host, options={"headers": headers}) + +#issues_Jql = jira_server.search_issues('filter=19527') #, expand='changelog') +issues_Jql = jira_server.search_issues('labels in (Refinement11012022) AND type not in (Bug) AND status not in (Done) and ("Story Points" is EMPTY or "Story Points" = 0)') #, expand='changelog') + +logging.info('Creating sub-tasks out of estimation of pre-planning sprint {}'.format(38)) +xsp = lambda s: s or 0 + +issue: Issue +for issue in issues_Jql: + logging.info('Working on {}'.format(issue)) + sp_sum = 0 + + # sp = 0 + # if hasattr(issue.fields, 'customfield_10022'): + # sp = xsp(issue.fields.customfield_10022) + # sp_sum += sp + + single_issue = jira_server.issue(issue.key) + comments = single_issue.fields.comment.comments + + # Find all comments made by me on this issue. + for comment in comments: + comment_lines = comment.body.splitlines() + + if len(comment_lines) == 5: + for comment_line in comment_lines: + if comment_line != "": + # pos = comment_lines[2].find('NN') + comment_line_parts = comment_line.split(':') + + # if 1. Test* != NN create a sub-task (if not existing) + if len(comment_line_parts) == 2: + if comment_line_parts[1] != u'\xa0': # empty string + if comment_line_parts[1][-2:] != 'NN': # NN means NotNecessary + subtask_ph = float(comment_line_parts[1]) * 0.5 + if comment_line_parts[0][:15] != "Test-Ausführung": + create_subtask(issue, + issue.key, + comment_line_parts[0], + subtask_ph) + sp_sum += subtask_ph / 0.5 + + # find corresponding sub-task + # issuelinks.inwardIssue + try: + issue.update(fields={'customfield_10022': sp_sum}) + logging.info("Estimated story-points changed to Sum(Sub-Tasks story-points): {}".format(sp_sum, sp_sum)) + + except exceptions.JIRAError: + logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key)) + + finally: + logging.info('Done {}'.format(issue.key)) + + #print('{}: {}, SP: {}'.format(issue.key, issue.fields.summary, sp)) + +#print('Summe {}: {}'.format(assignee, sp_sum)) + +#print(issues_Jql) +# changelog = issues_Jql. +# count = 0 +# for history in changelog.histories: +# for item in history.items: +# if item.field == 'status': +# if item.toString == "Reopened": +# count = count + 1 +# print(count) + diff --git a/JIRA_adapt_historical_estimations.py b/JIRA_adapt_historical_estimations.py new file mode 100644 index 0000000..22a6970 --- /dev/null +++ b/JIRA_adapt_historical_estimations.py @@ -0,0 +1,60 @@ +# recalculate historical estimations +# zisco 2021-10-05 15:54 + +import logging +from types import ClassMethodDescriptorType +from jira import JIRA, Issue, Comment, exceptions +import re +import csv +import xlsxwriter + +logging.basicConfig(filename='jahe.log', filemode='a', format='%(asctime)s - %(message)s', level=logging.INFO) + +host = "https://jira.wien.gv.at/" +pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" + +headers = JIRA.DEFAULT_OPTIONS["headers"].copy() +headers["Authorization"] = f"Bearer {pat}" +jira_server = JIRA(server=host, options={"headers": headers}) +logging.info("Connection to JIRA established") + +# issues_Jql = jira_server.search_issues('cf[10022] is not EMPTY AND labels not in (Refinement23092021, hotfix0921) AND status not in (Done) and key not in (wrgwr-929)', expand='changelog') +issues_Jql = jira_server.search_issues('key in (wrgwr-856, wrgwr-854, wrgwr-853)', expand='changelog') + +xsp = lambda s: s or 0 +sp_sum = 0 +issue: Issue +for issue in issues_Jql: + logging.info("Working on {}".format(issue.key)) + sp = 0 + if hasattr(issue.fields, 'customfield_10022'): + sp = xsp(issue.fields.customfield_10022) + sp_sum += sp + + # log old values + print(sp, sp/8) + originalEstimate = issue.fields.timeoriginalestimate + logging.info("Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8)) + + # probably already adapted? Search for activity 'updated the Story Points' + doChange = True + for history in issue.changelog.histories: + if doChange==False: + break + if (history.author.key=='JIRAUSER17211'): + for item in history.items: + if (item.field=='Story Points'): + doChange = False + break + + if doChange: + # update story-points + try: + issue.update(fields={'customfield_10022': sp/8}) + comment = jira_server.add_comment(issue, "Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8)) + + except exceptions.JIRAError: + logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key)) + + finally: + print('Done {}'.format(issue.key)) \ No newline at end of file diff --git a/JIRA_adapt_story_points.py b/JIRA_adapt_story_points.py new file mode 100644 index 0000000..c1e58ae --- /dev/null +++ b/JIRA_adapt_story_points.py @@ -0,0 +1,64 @@ +# suche alle issues, wo (original estimate * 2) != story points +# korrigiere story points auf original estimate * 2 + +# zisco 2021-10-05 15:54 + +import logging +from types import ClassMethodDescriptorType +from jira import JIRA, Issue, Comment, exceptions +import re +import csv +import xlsxwriter + +logging.basicConfig(filename='jahe.log', filemode='a', format='%(asctime)s - %(message)s', level=logging.INFO) + +host = "https://jira.wien.gv.at/" +pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" + +headers = JIRA.DEFAULT_OPTIONS["headers"].copy() +headers["Authorization"] = f"Bearer {pat}" +jira_server = JIRA(server=host, options={"headers": headers}) +logging.info("Connection to JIRA established") + +# issues_Jql = jira_server.search_issues('cf[10022] is not EMPTY AND labels not in (Refinement23092021, hotfix0921) AND status not in (Done) and key not in (wrgwr-929)', expand='changelog') +# issues_Jql = jira_server.search_issues('status not in (Done)', expand='changelog') +issues_Jql = jira_server.search_issues('key in (wrgwr-773)', expand='changelog') + +xsp = lambda s: s or 0 +sp_sum = 0 +issue: Issue +for issue in issues_Jql: + logging.info("Working on {}".format(issue.key)) + sp = 0 + if hasattr(issue.fields, 'customfield_10022'): + sp = xsp(issue.fields.customfield_10022) + sp_sum += sp + + # log old values + print(sp, sp/8) + originalEstimate = xsp(issue.fields.timeoriginalestimate) + logging.info("Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8)) + + if (originalEstimate != 0) and (originalEstimate / 14400) != sp: + # probably already adapted? Search for activity 'updated the Story Points' + doChange = True + for history in issue.changelog.histories: + if doChange==False: + break + if (history.author.key=='JIRAUSER17211'): + for item in history.items: + if (item.field=='Story Points'): + doChange = False + break + + if doChange: + # update story-points + try: + issue.update(fields={'customfield_10022': originalEstimate / 14400}) + comment = jira_server.add_comment(issue, "Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8)) + + except exceptions.JIRAError: + logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key)) + + finally: + print('Done {}'.format(issue.key)) \ No newline at end of file diff --git a/JIRA_import_ELSAP_work_log.py b/JIRA_import_ELSAP_work_log.py new file mode 100644 index 0000000..7b8f16d --- /dev/null +++ b/JIRA_import_ELSAP_work_log.py @@ -0,0 +1,219 @@ +#!/usr/bin/python3 + +# import work-log entries from elsap csv +# avoid multiple logging +# TODO: log completely + +# zisco 2021-10-28 09:33 + +import os, shutil +import logging +from types import ClassMethodDescriptorType +from jira import JIRA, Issue, Comment, exceptions, JIRAError +import re +import csv +from numpy import single +# import xlsxwriter +import pandas as pd +from pandas.core.dtypes.missing import notnull +import json + +from pandas.core.frame import DataFrame +from requests.sessions import codes + +def process_elsap_file(filename): + data = pd.read_excel(filename) + df = pd.DataFrame(data, columns=['Mitarbeiter','Datum','Menge.1','Benutzerfeld']) # dtype={'Mitarbeiter': str, 'Menge.1': float, 'Benutzerfeld': str}) + df = df.dropna() + #filtered_df = df.loc[(df['Datum'] >= '2021-10-01') + # & (df['Datum'] < '2021-11-02')] + df = df.loc[(df['Datum'] <= '2021-11-07')] + logging.info('Consider dates <= {}'.format('2021-11-07')) + + df['doit'] = True + df['new'] = False + df['del'] = False + df['JIRA'] = '' + + logging.info("Initial DataFrame size is {} rows".format(len(df.index))) + df = single_line_dataframe(df) + logging.info("Adapted DataFrame size is {} rows".format(len(df.index))) + + real = False + + for index, row in df.iterrows(): + # search for corresponding JIRA-issue + issue_str = "WRGWR-{}".format(row['JIRA']) + print("Working on {}".format(issue_str)) + logging.info("Working on {}".format(issue_str)) + + try: + worklogs = jira_server.worklogs(issue_str) + except JIRAError as e: + logging.error('JIRA-Iyssue {} not found! (status: {} text: {})'.format(issue_str, e.status_code, e.text)) + continue + + # probably work is already logged? + for worklog in worklogs: + # get corresponding user + jira_worklog_user = worklog.author.key + elsap_user = user_array[row['Mitarbeiter']] + + if jira_worklog_user==elsap_user: + if not confirm_prompt("User {} has already logged, still add worklog?".format(row['Mitarbeiter'])): + df.at[index,'doit'] = False + logging.info("No worklog wanted!") + + issue = jira_server.issue(issue_str) + originalEstimate = xsp(issue.fields.timeoriginalestimate) + + # TODO: Check if original time estimated set? (and, if it set well!) + if hasattr(issue.fields, 'customfield_10022'): + storypoints = xsp(issue.fields.customfield_10022) + if (storypoints/2*28800) != originalEstimate: + # adjust + if confirm_prompt("Adjust original-estimate with storypoints? (old {}, new {})".format(originalEstimate, storypoints/2*28800)): + if real == True: + issue.fields.timeoriginalestimate = storypoints/2*28800 # is that needed? + issue.update(fields={'timetracking': {'originalEstimate': '{}d'.format(storypoints/2)}}) + # print("Old {} new {}".format(storypoints, issue.fields.timeoriginalestimate)) + # logging.info("Old estimation {} should be changed to {} days (based on {} storypoints)".format(originalEstimate, storypoints/2, storypoints)) + logging.info("Old estimation {} changed to {} days (based on {} storypoints)".format(originalEstimate, storypoints/2, storypoints)) + + if row['doit'] == True: + if confirm_prompt("Add worklog for {}? ".format(issue_str)): + if real == True: + jira_server.add_worklog(issue_str, timeSpent="{}h".format(row['Menge.1']), user="{} worked on issue {} {} hours at {}".format(row['Mitarbeiter'], issue_str, row['Menge.1'], row['Datum'])) + # print(row['Datum'],row['Mitarbeiter'],row['Menge.1'],row['Benutzerfeld'],row['JIRA']) + logging.info("{} worked {} hours at {}".format(row['Mitarbeiter'], row['Menge.1'], row['Datum'])) + +def confirm_prompt(question: str) -> bool: + reply = None + while reply not in ("", "y", "n"): + reply = input(f"{question} (Y/n): ").lower() + return (reply in ("", "y")) + +def extract_jira_issues(comment): + if pd.notna(comment): + return re.findall(r'WRGWR-\d+', comment) + +""" + # possible values: Refinement (2), 1000 (2,5), Jour Fixe(1) + # 819(1),798(2),888(2), Meeting (1.5) + commentSplit = comment.split('),') + bookedJira = {} + singleJira = [] + for singleItem in commentSplit: + # a valid single item is a pair of two numerical values + singleJira = re.findall(r'\d+', singleItem) + if len(singleJira) == 2: + bookedJira[singleJira[0]] = singleJira[1] """ + # return bookedJira + +def single_line_dataframe(df) -> DataFrame: + for index, row in df.iterrows(): + issue_number = extract_jira_issues(row['Benutzerfeld']) + if issue_number: + if len(issue_number) > 1: + time = xsp(row['Menge.1'])/len(issue_number) # TODO: Consider possibility of given notation: "758 (2), 759 (1)" + df.at[index, 'del'] = True + + for single_issue in issue_number: # issue_number[1:] + new_rows = [] + # fix time of first entry, add as much as needed new lines + row.loc['Menge.1'] = time + row.loc['JIRA'] = single_issue + row.loc['new'] = True + new_rows.append(row) + df = df.append(pd.DataFrame(new_rows, columns=df.columns), ignore_index=True) # .reset_index() + else: + df.at[index, 'JIRA'] = issue_number + else: + df.at[index, 'doit'] = False + + # drop all to-be deleted rows + indexNames = df[df['del'] == True].index + df.drop(indexNames , inplace=True) + + # drop all non-doit + indexNames = df[df['doit'] == False].index + df.drop(indexNames , inplace=True) + + return df + +# map elsap-users to jira-users +# input_file = open('elsap_to_jira_user.json', encoding="utf-8") +userjson = '{"Kratochvil Jakub":"JIRAUSER16603","Zimmerberger Markus":"JIRAUSER17211","Cervenka Raimund":"JIRAUSER14400","Reischitz Ulf":"reu9001","Kremser Peter":"krp9002","Thüringer Helfried":"JIRAUSER15724","Blagojevic Nikolina":"JIRAUSER17212","Unfried Daniel":"und9001","Stefan Ion-Christian":"JIRAUSER16518"}' +user_array = json.loads(userjson) +# print(type(user_array)) + +logging.basicConfig(filename='elsap_importer.log', + filemode='a', + format='%(asctime)s - %(levelname)s: %(message)s', + level=logging.INFO, + encoding='utf-8') + +host = "https://jira.wien.gv.at/" +pat = "OTAyMTM3MjY0MjE0Ovz6bu0ti1TlEdSegmmiWiJ2wGeD" + +headers = JIRA.DEFAULT_OPTIONS["headers"].copy() +headers["Authorization"] = f"Bearer {pat}" +jira_server = JIRA(server=host, options={"headers": headers}) +logging.info("Connection to JIRA established") + +xsp = lambda s: s or 0 + +# open elsap-xlsx +with os.scandir(r'C:\Users\zim9003\Documents\reports') as it: + for entry in it: + if entry.name.endswith(".xlsx") and entry.is_file(): + logging.info('Processing file {}'.format(entry.path)) + + process_elsap_file(entry.path) + + # move to done + logging.info('Moved file to done -> {}'.format(entry.name)) + shutil.move(entry.path, r'C:\Users\zim9003\Documents\reports\done\{}'.format(entry.name)) + +# issues_Jql = jira_server.search_issues('cf[10022] is not EMPTY AND labels not in (Refinement23092021, hotfix0921) AND status not in (Done) and key not in (wrgwr-929)', expand='changelog') +# issues_Jql = jira_server.search_issues('status not in (Done)', expand='changelog') +""" issues_Jql = jira_server.search_issues('key in (wrgwr-773)', expand='changelog') + +xsp = lambda s: s or 0 +sp_sum = 0 +issue: Issue +for issue in issues_Jql: + logging.info("Working on {}".format(issue.key)) + sp = 0 + if hasattr(issue.fields, 'customfield_10022'): + sp = xsp(issue.fields.customfield_10022) + sp_sum += sp + + # log old values + print(sp, sp/8) + originalEstimate = xsp(issue.fields.timeoriginalestimate) + logging.info("Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8)) + + if (originalEstimate != 0) and (originalEstimate / 14400) != sp: + # probably already adapted? Search for activity 'updated the Story Points' + doChange = True + for history in issue.changelog.histories: + if doChange==False: + break + if (history.author.key=='JIRAUSER17211'): + for item in history.items: + if (item.field=='Story Points'): + doChange = False + break + + if doChange: + # update story-points + try: + issue.update(fields={'customfield_10022': originalEstimate / 14400}) + comment = jira_server.add_comment(issue, "Estimation-system change: Old Story Points {} -> new Story Points {}".format(sp, sp/8)) + + except exceptions.JIRAError: + logging.error("Issue {} has no (visible) Story Points-attribute".format(issue.key)) + + finally: + print('Done {}'.format(issue.key)) """ \ No newline at end of file diff --git a/elsap_to_jira_user.json b/elsap_to_jira_user.json new file mode 100644 index 0000000..097af62 --- /dev/null +++ b/elsap_to_jira_user.json @@ -0,0 +1,25 @@ +[{ + "Kratochvil Jakub": "JIRAUSER16603", "games": ["Spiderman","God of War"] +}, +{ + "JIRAUSER17211": "Zimmerberger Markus" +}, +{ + "Cervenka Raimund": "JIRAUSER14400" +}, +{ + "Reischitz Ulf": "reu9001" +}, +{ + "Kremser Peter": "krp9002" +}, +{ + "Thüringer Helfried": "JIRAUSER15724" +}, +{ + "Blagojevic Nikolina": "JIRAUSER17212" +}, +{ + "Unfried Daniel": "und9001" +} +] \ No newline at end of file diff --git a/elsap_to_jira_user_old.json b/elsap_to_jira_user_old.json new file mode 100644 index 0000000..bc8ba01 --- /dev/null +++ b/elsap_to_jira_user_old.json @@ -0,0 +1,41 @@ +[{ + "elsap": "Kratochvil Jakub", + "name": "krj0003", + "key": "JIRAUSER16603" +}, +{ + "elsap": "Zimmerberger Markus", + "name": "zim9003", + "key": "JIRAUSER17211" +}, +{ + "elsap": "Cervenka Raimund", + "name": "ce39001", + "key": "JIRAUSER14400" +}, +{ + "elsap": "Reischitz Ulf", + "name": "reu9001", + "key": "reu9001" +}, +{ + "elsap": "Kremser Peter", + "name": "krp9002", + "key": "krp9002" +}, +{ + "elsap": "Thüringer Helfried", + "name": "thh9001", + "key": "JIRAUSER15724" +}, +{ + "elsap": "Blagojevic Nikolina", + "name": "bln9001", + "key": "JIRAUSER17212" +}, +{ + "elsap": "Unfried Daniel", + "name": "und9001", + "key": "und9001" +} +] \ No newline at end of file