{"id":2438,"date":"2014-12-26T16:46:47","date_gmt":"2014-12-26T07:46:47","guid":{"rendered":"http:\/\/www.skyarch.net\/blog\/?p=2438"},"modified":"2016-08-07T07:30:42","modified_gmt":"2016-08-06T22:30:42","slug":"backlogapi%e6%9c%89%e5%8a%b9%e6%b4%bb%e7%94%a8-%e9%80%b1%e6%ac%a1%e3%83%ac%e3%83%9d%e3%83%bc%e3%83%88","status":"publish","type":"post","link":"https:\/\/www.skyarch.net\/blog\/backlogapi%e6%9c%89%e5%8a%b9%e6%b4%bb%e7%94%a8-%e9%80%b1%e6%ac%a1%e3%83%ac%e3%83%9d%e3%83%bc%e3%83%88\/","title":{"rendered":"BacklogAPI\u6709\u52b9\u6d3b\u7528 -\u9031\u6b21\u30ec\u30dd\u30fc\u30c8-"},"content":{"rendered":"<h1>\u76ee\u7684<\/h1>\n<p>\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8ab2\u984c\u304c\u4eca\u9031\u306b\u3069\u306e\u7a0b\u5ea6\u66f4\u65b0\u3055\u308c\u3001\u305d\u306e\u3046\u3061\u3069\u306e\u7a0b\u5ea6\u304c\u5b8c\u4e86\u3057\u305f\u304b\u8abf\u3079\u305f\u3044<br \/>\n\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u8907\u6570\u6a2a\u65ad\u3057\u3066\u3001\u305d\u306e\u9031\u306b\u66f4\u65b0\u3055\u308c\u305f\u30c1\u30b1\u30c3\u30c8\u3092\u96c6\u3081\u308b<\/p>\n<h1>\u3084\u3063\u3066\u307f\u305f\u4e8b<\/h1>\n<p>\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306b\u8a18\u8ff0\u3055\u308c\u305f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067<br \/>\n\u305d\u306e\u9031\u306b\u66f4\u65b0\u3055\u308c\u305f\u8ab2\u984c\u3092\u4ee3\u8868\u8005\u306e\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306b\u9001\u4fe1\u3059\u308b<\/p>\n<h1>\u9001\u4fe1\u3055\u308c\u308b\u30ec\u30dd\u30fc\u30c8\u30e1\u30fc\u30eb\u30b5\u30f3\u30d7\u30eb<\/h1>\n<p>\u4ee3\u8868\u8005\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306b\u305d\u306e\u9031\u306b\u66f4\u65b0\u304c\u3042\u3063\u305f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8<br \/>\n\u3068\u305d\u306e\u8ab2\u984c\u304c\u30e1\u30fc\u30eb\u9001\u4fe1\u3055\u308c\u307e\u3059<\/p>\n<blockquote><p>\u25bc [PRJ_NAME]\n\u30c1\u30b1\u30c3\u30c8 4\u4ef6 \u66f4\u65b0 \u5185\u5b8c\u4e86 2\u4ef6<br \/>\n[PRJ_NAME-10] \u8ab2\u984c\u306e\u6982\u8981<br \/>\n[PRJ_NAME-15] \u8ab2\u984c\u306e\u6982\u8981<br \/>\n[PRJ_NAME-22] \u8ab2\u984c\u306e\u6982\u8981<br \/>\n[PRJ_NAME-31] \u8ab2\u984c\u306e\u6982\u8981<\/p>\n<p>\u2026<\/p>\n<p>&nbsp;<\/p>\n<p>\u25bc [PRJ_NAME]\n\u30c1\u30b1\u30c3\u30c8 3\u4ef6 \u66f4\u65b0 \u5185\u5b8c\u4e86 0\u4ef6<br \/>\n[PRJ_NAME-3] \u8ab2\u984c\u306e\u6982\u8981<br \/>\n[PRJ_NAME-11] \u8ab2\u984c\u306e\u6982\u8981<br \/>\n[PRJ_NAME-20] \u8ab2\u984c\u306e\u6982\u8981<\/p>\n<p>\u2026<\/p><\/blockquote>\n<h1>\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\"config.ini\"\u306e\u8a18\u8ff0\u4f8b<\/h1>\n<p>Windows\u306eini\u30d5\u30a1\u30a4\u30eb\u306e\u69cb\u6587\u306b\u5f93\u3063\u3066\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u3092\u8a18\u8ff0\u3057\u307e\u3059<\/p>\n<blockquote>\n<pre class=\"loom_code prettyprint prettyprinted\"><span class=\"com\"># \u60c5\u5831\u3092\u53d6\u5f97\u3059\u308bBACKLOG\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u540d\u79f0(\u8907\u6570\u6307\u5b9a\u53ef)<\/span>\n<span class=\"pun\">[<\/span><span class=\"typ\">ProjectName<\/span><span class=\"pun\">]<\/span><span class=\"pln\">\nproject<\/span><span class=\"pun\">:PROJECT<\/span><span class=\"pln\">_1\n        HOGE_PRJ\n        HUGAHUGA_SVC\n        HOMUHOMU_AKM\n        AWS_TEST\n        NIFTY_ACT\n        NIKONIKONI\n        WEB_PUB_RELEASE\n        UNIT-TANAKA<\/span><\/pre>\n<pre class=\"loom_code prettyprint prettyprinted\"><span class=\"com\"># \u4ee3\u8868\u8005\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9<\/span>\n<span class=\"pun\">[<\/span><span class=\"typ\">ChiefAddress<\/span><span class=\"pun\">]<\/span><span class=\"pln\">\naddress <\/span><span class=\"pun\">=<\/span><span class=\"pln\"> hogefoobar2015<\/span><span class=\"pln\">@example<\/span><span class=\"pun\">.<\/span><span class=\"pln\">com<\/span><\/pre>\n<\/blockquote>\n<pre class=\"loom_code prettyprint prettyprinted\"><span class=\"com\">\u00a0<\/span><\/pre>\n<h1 class=\"loom_code prettyprint prettyprinted\"><span class=\"pln\">\u30d7\u30ed\u30b0\u30e9\u30e0\u672c\u4f53<\/span><\/h1>\n<p>&nbsp;<\/p>\n<h2>\u52d5\u4f5c\u78ba\u8a8d\u74b0\u5883<\/h2>\n<ul>\n<li>Python2.6.6<\/li>\n<li>backloglib(python)<\/li>\n<\/ul>\n<p><a href=\"https:\/\/code.google.com\/p\/backloglib\/\">https:\/\/code.google.com\/p\/backloglib\/<\/a><\/p>\n<h2>\u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb<\/h2>\n<p>\u30d7\u30ed\u30b0\u30e9\u30e0\u3068\u540c\u3058\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u914d\u7f6e\u306e\u4e0a<br \/>\n\u30d5\u30a1\u30a4\u30eb\u540d\u3092config.ini\u3068\u3057\u3066\u304f\u3060\u3055\u3044<\/p>\n<h2>\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9<\/h2>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n# -*- coding: utf-8 -*-\r\n\r\n#####\r\n## FileName:report_mail_weekly.py\r\n## Author:Ryo Tanaka\r\n## Version:0.1.1\r\n## Date:2014\/12\/25\r\n## Usage:.\/report_mail_weekly.py\r\n## Summary:\u66f4\u65b0\u304c\u4eca\u9031\u306eBACKLOG\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30b5\u30de\u30ea\u3092\u30e1\u30fc\u30eb\u9001\u4fe1\u3057\u307e\u3059\r\n#####\r\n\r\n__author__ = 'tanaka'\r\nimport math\r\nimport datetime\r\nimport backloglib\r\nimport smtplib\r\nimport ConfigParser\r\nfrom email.MIMEText import MIMEText\r\nfrom email.Header import Header\r\nfrom email.Utils import formatdate\r\n\r\n############\r\n# \u8a2d\u5b9a\u9805\u76ee #\r\n############\r\nconfig_file = &quot;config.ini&quot;\r\n\r\nspacename = &quot;\u30b9\u30da\u30fc\u30b9\u30cd\u30fc\u30e0\u3092\u8a18\u8f09 xxxx.backlog.jp \u306e\u90e8\u5206\u3067\u3059&quot;\r\nusername = &quot;API\u7528\u30e6\u30fc\u30b6\u30cd\u30fc\u30e0\u3092\u8a18\u8f09 API\u30ea\u30af\u30a8\u30b9\u30c8\u306b\u4f7f\u3046\u30e6\u30fc\u30b6\u540d&quot;\r\npassword = &quot;API\u7528\u30e6\u30fc\u30b6\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u8a18\u8f09 API\u30ea\u30af\u30a8\u30b9\u30c8\u306b\u4f7f\u3046\u30e6\u30fc\u30b6\u306e\u30d1\u30b9\u30ef\u30fc\u30c9&quot;\r\n\r\nsmtpsvr = &quot;\u30e1\u30fc\u30eb\u9001\u4fe1\u30b5\u30fc\u30d0\u30a2\u30c9\u30ec\u30b9&quot;\r\nport = 25\r\n\r\nfrom_addr = '\u30e1\u30fc\u30eb\u9001\u4fe1\u5143\u30a2\u30c9\u30ec\u30b9\u3092\u8a18\u8f09'\r\n\r\n#\r\n# get_week_start \u305d\u306e\u9031\u306e\u521d\u3081\u3092\u53d6\u5f97\u3057\u307e\u3059\r\n# @param today datetime.datetime.today\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\r\n# @return week_start \u9031\u306e\u521d\u3081\u306e\u897f\u66a6(YYYYMMDD)\r\n#\r\ndef get_week_start(today):\r\n    week_start = today + datetime.timedelta(days=-week_start_offset)\r\n    week_start = week_start.strftime('%Y%m%d')\r\n    return week_start\r\n\r\n#\r\n# get_week_end \u305d\u306e\u9031\u306e\u7d42\u308f\u308a\u3092\u53d6\u5f97\u3057\u307e\u3059\r\n# @param today datetime.datetime.today\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\r\n# @return week_end \u9031\u306e\u7d42\u308f\u308a\u306e\u897f\u66a6(YYYYMMDD)\r\n#\r\ndef get_week_end(today):\r\n    week_end = today + datetime.timedelta(days=week_end_offset)\r\n    week_end = week_end.strftime('%Y%m%d')\r\n    return week_end\r\n\r\n#\r\n# create_message MIMEText\u3092\u4f5c\u6210\r\n# @param from_addr \u9001\u4fe1\u5143\u30a2\u30c9\u30ec\u30b9\r\n# @param to_addr \u9001\u4fe1\u5148\u30a2\u30c9\u30ec\u30b9\r\n# @param subject \u4ef6\u540d\r\n# @param body \u30e1\u30fc\u30eb\u672c\u6587\r\n# @param encoding \u6587\u5b57\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\r\n# @return msg MIMEText\r\n#\r\ndef create_message(from_addr, to_addr, subject, body, encoding):\r\n    msg = MIMEText(body, 'plain', encoding)\r\n    msg&#x5B;'Subject'] = Header(subject, encoding)\r\n    msg&#x5B;'From'] = from_addr\r\n    msg&#x5B;'To'] = to_addr\r\n    msg&#x5B;'Date'] = formatdate(localtime=True)\r\n    msg&#x5B;'X-Priority'] = '1'\r\n    return msg\r\n\r\n#\r\n# send_mail \u30e1\u30fc\u30eb\u9001\u4fe1\r\n# @param from_addr \u9001\u4fe1\u5143\u30a2\u30c9\u30ec\u30b9\r\n# @param to_addr \u9001\u4fe1\u5148\u30a2\u30c9\u30ec\u30b9\r\n# @param msg \u9001\u4fe1\u3059\u308bMIMEText\r\n#\r\ndef send_mail(from_addr, to_addr, msg):\r\n    smtp = smtplib.SMTP(smtpsvr, port)\r\n    smtp.sendmail(from_addr, &#x5B;to_addr], msg.as_string())\r\n    smtp.close()\r\n\r\n#\r\n# make_report \u5831\u544a\u30ec\u30dd\u30fc\u30c8\u4f5c\u6210\r\n# @param project \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u540d\r\n# @param summary \u8ab2\u984c\u306e\u6982\u8981\r\n# @param issue \u8ab2\u984c\u30ad\u30fc\r\n# @param total \u8ab2\u984c\u6570\r\n# @param finish_total \u5b8c\u4e86\u3057\u305f\u8ab2\u984c\u6570\r\n# @return rep \u69cb\u7bc9\u3055\u308c\u305f\u30ec\u30dd\u30fc\u30c8\r\n#\r\ndef make_report(project, issue, summary, total, finish_total):\r\n    rep = u&quot;\u25bc &#x5B;&quot; + project + u&quot;]&quot; + &quot;\\n&quot; \\\r\n        + u&quot;\u30c1\u30b1\u30c3\u30c8 &quot; + str(total) + u&quot;\u4ef6 \u66f4\u65b0 \u5185\u5b8c\u4e86 &quot; + str(finish_total) + u&quot;\u4ef6&quot; + &quot;\\n&quot; \\\r\n        + u&quot;&#x5B;&quot; + issue + u&quot;] &quot; + summary + &quot;\\n&quot;\r\n\r\n    return rep\r\n\r\n#\r\n# append_report \u5831\u544a\u30ec\u30dd\u30fc\u30c8\u8ffd\u8a18\r\n# @param report \u8ffd\u8a18\u5143\u30ec\u30dd\u30fc\u30c8\r\n# @param issue \u8ffd\u8a18\u8ab2\u984c\u30ad\u30fc\r\n# @param summary \u8ffd\u8a18\u8ab2\u984c\u6982\u8981\r\n#\r\ndef append_report(report, issue, summary):\r\n    rep = report + u&quot;&#x5B;&quot; + issue + u&quot;] &quot; + summary + &quot;\\n&quot;\r\n    return rep\r\n\r\n# #### #\r\n# MAIN #\r\n# #### #\r\nif __name__ == &quot;__main__&quot; :\r\n\r\n    config = ConfigParser.SafeConfigParser()\r\n    config.read(&quot;.\/config.ini&quot;)\r\n\r\n    projects = config.get(&quot;ProjectName&quot;, &quot;project&quot;)\r\n    projects = projects.splitlines()\r\n\r\n    chief_addr = config.get(&quot;ChiefAddress&quot;, &quot;address&quot;)\r\n\r\n    today = datetime.datetime.today()\r\n    week_start_offset = int(str(today.weekday()))\r\n    week_end_offset = 7 - week_start_offset\r\n    week_start = get_week_start(today)\r\n    week_end = get_week_end(today)\r\n\r\n    compiled_report = &quot;&quot;\r\n\r\n    backlog = backloglib.Backlog(spacename, username, password)\r\n\r\n    for prj_index in range(len(projects)):\r\n\r\n        project = backlog.get_project(projects&#x5B;prj_index])\r\n        report_subject = &quot;\u3010BACKLOG\u3011&quot; + project.key + &quot;\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u9031\u6b21\u30ec\u30dd\u30fc\u30c8&quot;\r\n\r\n        issues = backlog.find_issue({\r\n                                        'projectId':project.id,\r\n                                        'sort':&quot;DUE_DATE&quot;,\r\n                                        'updated_on_min':week_start,\r\n                                        'updated_on_max':week_end,\r\n                                        'order':1\r\n                                   })\r\n\r\n        issues_finished = backlog.find_issue({\r\n                                                 'projectId':project.id,\r\n                                                 'statusId': 4,\r\n                                                 'sort':&quot;CREATED&quot;,\r\n                                                 'updated_on_min':week_start,\r\n                                                 'updated_on_max':week_end,\r\n                                                 'order':1\r\n                                            })\r\n\r\n        total = len(issues)\r\n        total_finished = len(issues_finished)\r\n\r\n        if len(issues) &lt; 1:\r\n            continue\r\n\r\n        report = &#x5B;0 for cnt in range(len(projects))]\r\n\r\n        for issue_index in range(len(issues)):\r\n\r\n            issue = backlog.get_issue(issues&#x5B;issue_index].id)\r\n\r\n            if issue_index == 0:\r\n                rep_section = make_report(project.key, issues&#x5B;issue_index].key, issues&#x5B;issue_index].summary, total, total_finished)\r\n                report&#x5B;prj_index] = rep_section\r\n            else:\r\n                report&#x5B;prj_index] = append_report(report&#x5B;prj_index], issues&#x5B;issue_index].key, issues&#x5B;issue_index].summary)\r\n\r\n        report&#x5B;prj_index] = report&#x5B;prj_index].encode('utf-8')\r\n        compiled_report += report&#x5B;prj_index] + &quot;\\n&quot;\r\n\r\n    report = &quot;&quot;.join(map(str, report)) # \u914d\u5217\u3092\u7d50\u5408\r\n\r\nwhole_msg = create_message(from_addr, chief_addr, report_subject, str(compiled_report), 'utf-8')\r\nsend_mail(from_addr, chief_addr, whole_msg)\r\nexit(0)\r\n<\/pre>\n<h2>config.ini\u30b5\u30f3\u30d7\u30eb<\/h2>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n# \u60c5\u5831\u3092\u53d6\u5f97\u3059\u308bBACKLOG\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u540d\u79f0(\u8907\u6570\u6307\u5b9a\u53ef)\r\n&#x5B;ProjectName]\r\nproject:TEST1\r\n        TEST2\r\n\r\n# \u4ee3\u8868\u8005\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\r\n&#x5B;ChiefAddress]\r\naddress = test@test.com\r\n<\/pre>\n<h2>\u304a\u8a6b\u3073<\/h2>\n<p>2015\/01\/29 \u306b\u4e0a\u8a18\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9\u306e\u30e1\u30fc\u30eb\u9001\u4fe1\u90e8\u5206\u306b\u3066\u30a8\u30e9\u30fc\u304c\u8d77\u304d\u3066\u3057\u307e\u3046\u90e8\u5206\u3092\u4fee\u6b63\u3057\u307e\u3057\u305f\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u76ee\u7684 \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u8ab2\u984c\u304c\u4eca\u9031\u306b\u3069\u306e\u7a0b\u5ea6\u66f4\u65b0\u3055\u308c\u3001\u305d\u306e\u3046\u3061\u3069\u306e\u7a0b\u5ea6\u304c\u5b8c\u4e86\u3057\u305f\u304b\u8abf\u3079\u305f\u3044 \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u8907\u6570\u6a2a\u65ad\u3057\u3066\u3001\u305d\u306e\u9031\u306b\u66f4\u65b0\u3055\u308c\u305f\u30c1\u30b1\u30c3\u30c8\u3092\u96c6\u3081\u308b \u3084\u3063\u3066\u307f\u305f\u4e8b \u8a2d\u5b9a\u30d5\u30a1\u30a4\u30eb\u306b\u8a18\u8ff0\u3055\u308c\u305f\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067 \u305d\u306e\u9031\u306b\u66f4\u65b0\u3055&#8230;<\/p>\n","protected":false},"author":1,"featured_media":2452,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"ja","_original_post":"2438","footnotes":""},"categories":[9],"tags":[39,13,65],"class_list":{"0":"post-2438","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-dev","8":"tag-api","9":"tag-backlog","10":"tag-python","11":"ja"},"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts\/2438","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/comments?post=2438"}],"version-history":[{"count":17,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts\/2438\/revisions"}],"predecessor-version":[{"id":2608,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/posts\/2438\/revisions\/2608"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/media\/2452"}],"wp:attachment":[{"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/media?parent=2438"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/categories?post=2438"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyarch.net\/blog\/wp-json\/wp\/v2\/tags?post=2438"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}