prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Users who are retaking their third year are automatically set to first grade
  <!-- If this is a security issue or information leakage (having access to something you (probably) shouldn't), please send an email rather than opening a public issue. -->
  
  ## What kind of an issue is this?
  
  - Bug report
  - Feature request
  
  
  ## What is the expected behaviour?
  Users who are retaking their third year and apply for an extended membership should be put in the third grade. This should happen when using the dataporten application. 
  
  ## What is the current behaviour?
  
  Users who are retaking their third year are automatically set to first grade when using the automatic application system.
  
  <!-- if this is a bug report -->
  
  
  ## How do you reproduce this problem? 
  
  <!-- if this is a bug report -->
  <!-- provide steps to reproduce this problem, preferably in a bullet point list -->
  
  * Be doing extra year of informatikk after third year. 
  * Use automatic membership application to extend your membership. 
  * Cry. 
  
  ## Other information
  
  <!-- include screenshots if appropriate -->
  <!-- add labels you see fit. please do not exaggerate. -->
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `apps/dataporten/study/utils.py`
  Content:
  ```
  1 import logging
  2 
  3 from dateutil.parser import parse
  4 from django.utils import timezone
  5 
  6 from apps.authentication.constants import FieldOfStudyType
  7 from apps.dataporten.study.courses import GROUP_IDENTIFIERS, MASTER_IDS
  8 
  9 logger = logging.getLogger(__name__)
  10 
  11 
  12 def get_study(groups):
  13     study_group = {}
  14     for group in groups:
  15         if group.get("id") == GROUP_IDENTIFIERS["BACHELOR"]:
  16             logger.debug("User found to be bachelor student")
  17             study_group = group
  18             break
  19 
  20         elif group.get("id") == GROUP_IDENTIFIERS["MASTER_OLD"]:
  21             logger.debug("User found to be master student on old programme")
  22             study_group = group
  23             break
  24 
  25         elif group.get("id") == GROUP_IDENTIFIERS["MASTER"]:
  26             logger.debug("User found to be master student")
  27             study_group = group
  28             break
  29 
  30     return study_group
  31 
  32 
  33 def get_group_id(group):
  34     return group.get("id", "")
  35 
  36 
  37 def get_group_name(group):
  38     return group.get("displayName", "")
  39 
  40 
  41 def get_course_finish_date(course):
  42     if "membership" in course:
  43         if "notAfter" in course["membership"]:
  44             # User has finished this course
  45             raw_datetime = course.get("membership", {}).get("notAfter", "")
  46             try:
  47                 # Date format: 2014-08-14T22:00:00Z
  48                 return parse(raw_datetime)
  49             except ValueError:
  50                 logger.error('Failed to parse datetime "%s".' % raw_datetime)
  51     return None
  52 
  53 
  54 def get_add_years(course):
  55     """Add years back for more recent courses.
  56         If course is 2nd grade, the user started one more year before."""
  57     # Add 1 year if verification happens during fall, 0 if during spring.
  58     add_years = 1 if timezone.now().month >= 7 else 0
  59 
  60     if course["id"] == GROUP_IDENTIFIERS["PROSJEKT1"]:
  61         add_years += 1
  62     elif course["id"] == GROUP_IDENTIFIERS["ALGDAT"]:
  63         add_years += 1
  64     elif course["id"] == GROUP_IDENTIFIERS["PROSJEKT2"]:
  65         add_years += 3
  66 
  67     return min(3, add_years)
  68 
  69 
  70 def get_year_from_course(course, date):
  71     return (timezone.now().year - date.year) + get_add_years(course)
  72 
  73 
  74 def get_bachelor_year(groups):
  75     years = []
  76     for group in groups:
  77         if group.get("id") in GROUP_IDENTIFIERS.values():
  78             logger.debug("Finding study year from {}".format(group.get("id")))
  79             parsed_datetime = get_course_finish_date(group)
  80             if parsed_datetime:
  81                 years.append(get_year_from_course(group, parsed_datetime))
  82             else:
  83                 # If we don't know the end date, only add the years for the course.
  84                 years.append(get_add_years(group))
  85 
  86     return max(years)
  87 
  88 
  89 def get_master_year(groups):
  90     for group in groups:
  91         if group.get("id") in MASTER_IDS:
  92             logger.debug("Identified master study course: %s" % group.get("id"))
  93             return 5
  94     return 4
  95 
  96 
  97 def get_year(study_id, groups):
  98     if study_id == GROUP_IDENTIFIERS["BACHELOR"]:
  99         return get_bachelor_year(groups)
  100     elif study_id == GROUP_IDENTIFIERS["MASTER"]:
  101         return get_master_year(groups)
  102     else:
  103         return 0
  104 
  105 
  106 def get_field_of_study(groups):
  107     if get_group_id(get_study(groups)) == GROUP_IDENTIFIERS["BACHELOR"]:
  108         return FieldOfStudyType.BACHELOR
  109     else:
  110         found_master_study = False
  111         for group in groups:
  112             group_id = get_group_id(group)
  113             if group_id in (
  114                 GROUP_IDENTIFIERS["MASTER_SPEC_PVS_OLD"],
  115                 GROUP_IDENTIFIERS["MASTER_SPEC_SWE"],
  116             ):
  117                 return FieldOfStudyType.SOFTWARE_ENGINEERING
  118             elif group_id in (
  119                 GROUP_IDENTIFIERS["MASTER_SPEC_DBS_OLD"],
  120                 GROUP_IDENTIFIERS["MASTER_SPEC_DBS"],
  121             ):
  122                 return FieldOfStudyType.DATABASE_AND_SEARCH
  123             elif group_id in (
  124                 GROUP_IDENTIFIERS["MASTER_SPEC_KI_OLD"],
  125                 GROUP_IDENTIFIERS["MASTER_SPEC_AI"],
  126             ):
  127                 return FieldOfStudyType.ARTIFICIAL_INTELLIGENCE
  128             elif group_id in (
  129                 GROUP_IDENTIFIERS["MASTER_SPEC_UX_OLD"],
  130                 GROUP_IDENTIFIERS["MASTER_SPEC_UX"],
  131             ):
  132                 return FieldOfStudyType.INTERACTION_DESIGN
  133             elif group_id == GROUP_IDENTIFIERS["MASTER_COURSE_OTHER"]:
  134                 return FieldOfStudyType.OTHER_MASTERS
  135             elif group_id in (
  136                 GROUP_IDENTIFIERS["MASTER"],
  137                 GROUP_IDENTIFIERS["MASTER_OLD"],
  138             ):
  139                 found_master_study = True
  140 
  141         # If we don't find a specific master study, return 'other'
  142         if found_master_study:
  143             return FieldOfStudyType.OTHER_MASTERS
  144 
  145     # Return guest if we find nothing else
  146     return FieldOfStudyType.GUEST
  147
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/apps/dataporten/study/utils.py b/apps/dataporten/study/utils.py
  --- a/apps/dataporten/study/utils.py
  +++ b/apps/dataporten/study/utils.py
  @@ -83,7 +83,8 @@
                   # If we don't know the end date, only add the years for the course.
                   years.append(get_add_years(group))
   
  -    return max(years)
  +    # Allows for users with extended bachelors to retain year 3 privileges.
  +    return max(years) if max(years) <= 3 else 3
   
   
   def get_master_year(groups):
  
verification_info: {"golden_diff": "diff --git a/apps/dataporten/study/utils.py b/apps/dataporten/study/utils.py\n--- a/apps/dataporten/study/utils.py\n+++ b/apps/dataporten/study/utils.py\n@@ -83,7 +83,8 @@\n                 # If we don't know the end date, only add the years for the course.\n                 years.append(get_add_years(group))\n \n-    return max(years)\n+    # Allows for users with extended bachelors to retain year 3 privileges.\n+    return max(years) if max(years) <= 3 else 3\n \n \n def get_master_year(groups):\n", "issue": "Users who are retaking their third year are automatically set to first grade\n<!-- If this is a security issue or information leakage (having access to something you (probably) shouldn't), please send an email rather than opening a public issue. -->\r\n\r\n## What kind of an issue is this?\r\n\r\n- Bug report\r\n- Feature request\r\n\r\n\r\n## What is the expected behaviour?\r\nUsers who are retaking their third year and apply for an extended membership should be put in the third grade. This should happen when using the dataporten application. \r\n\r\n## What is the current behaviour?\r\n\r\nUsers who are retaking their third year are automatically set to first grade when using the automatic application system.\r\n\r\n<!-- if this is a bug report -->\r\n\r\n\r\n## How do you reproduce this problem? \r\n\r\n<!-- if this is a bug report -->\r\n<!-- provide steps to reproduce this problem, preferably in a bullet point list -->\r\n\r\n* Be doing extra year of informatikk after third year. \r\n* Use automatic membership application to extend your membership. \r\n* Cry. \r\n\r\n## Other information\r\n\r\n<!-- include screenshots if appropriate -->\r\n<!-- add labels you see fit. please do not exaggerate. -->\r\n\n", "before_files": [{"content": "import logging\n\nfrom dateutil.parser import parse\nfrom django.utils import timezone\n\nfrom apps.authentication.constants import FieldOfStudyType\nfrom apps.dataporten.study.courses import GROUP_IDENTIFIERS, MASTER_IDS\n\nlogger = logging.getLogger(__name__)\n\n\ndef get_study(groups):\n    study_group = {}\n    for group in groups:\n        if group.get(\"id\") == GROUP_IDENTIFIERS[\"BACHELOR\"]:\n            logger.debug(\"User found to be bachelor student\")\n            study_group = group\n            break\n\n        elif group.get(\"id\") == GROUP_IDENTIFIERS[\"MASTER_OLD\"]:\n            logger.debug(\"User found to be master student on old programme\")\n            study_group = group\n            break\n\n        elif group.get(\"id\") == GROUP_IDENTIFIERS[\"MASTER\"]:\n            logger.debug(\"User found to be master student\")\n            study_group = group\n            break\n\n    return study_group\n\n\ndef get_group_id(group):\n    return group.get(\"id\", \"\")\n\n\ndef get_group_name(group):\n    return group.get(\"displayName\", \"\")\n\n\ndef get_course_finish_date(course):\n    if \"membership\" in course:\n        if \"notAfter\" in course[\"membership\"]:\n            # User has finished this course\n            raw_datetime = course.get(\"membership\", {}).get(\"notAfter\", \"\")\n            try:\n                # Date format: 2014-08-14T22:00:00Z\n                return parse(raw_datetime)\n            except ValueError:\n                logger.error('Failed to parse datetime \"%s\".' % raw_datetime)\n    return None\n\n\ndef get_add_years(course):\n    \"\"\"Add years back for more recent courses.\n        If course is 2nd grade, the user started one more year before.\"\"\"\n    # Add 1 year if verification happens during fall, 0 if during spring.\n    add_years = 1 if timezone.now().month >= 7 else 0\n\n    if course[\"id\"] == GROUP_IDENTIFIERS[\"PROSJEKT1\"]:\n        add_years += 1\n    elif course[\"id\"] == GROUP_IDENTIFIERS[\"ALGDAT\"]:\n        add_years += 1\n    elif course[\"id\"] == GROUP_IDENTIFIERS[\"PROSJEKT2\"]:\n        add_years += 3\n\n    return min(3, add_years)\n\n\ndef get_year_from_course(course, date):\n    return (timezone.now().year - date.year) + get_add_years(course)\n\n\ndef get_bachelor_year(groups):\n    years = []\n    for group in groups:\n        if group.get(\"id\") in GROUP_IDENTIFIERS.values():\n            logger.debug(\"Finding study year from {}\".format(group.get(\"id\")))\n            parsed_datetime = get_course_finish_date(group)\n            if parsed_datetime:\n                years.append(get_year_from_course(group, parsed_datetime))\n            else:\n                # If we don't know the end date, only add the years for the course.\n                years.append(get_add_years(group))\n\n    return max(years)\n\n\ndef get_master_year(groups):\n    for group in groups:\n        if group.get(\"id\") in MASTER_IDS:\n            logger.debug(\"Identified master study course: %s\" % group.get(\"id\"))\n            return 5\n    return 4\n\n\ndef get_year(study_id, groups):\n    if study_id == GROUP_IDENTIFIERS[\"BACHELOR\"]:\n        return get_bachelor_year(groups)\n    elif study_id == GROUP_IDENTIFIERS[\"MASTER\"]:\n        return get_master_year(groups)\n    else:\n        return 0\n\n\ndef get_field_of_study(groups):\n    if get_group_id(get_study(groups)) == GROUP_IDENTIFIERS[\"BACHELOR\"]:\n        return FieldOfStudyType.BACHELOR\n    else:\n        found_master_study = False\n        for group in groups:\n            group_id = get_group_id(group)\n            if group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_PVS_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_SWE\"],\n            ):\n                return FieldOfStudyType.SOFTWARE_ENGINEERING\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_DBS_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_DBS\"],\n            ):\n                return FieldOfStudyType.DATABASE_AND_SEARCH\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_KI_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_AI\"],\n            ):\n                return FieldOfStudyType.ARTIFICIAL_INTELLIGENCE\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_UX_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_UX\"],\n            ):\n                return FieldOfStudyType.INTERACTION_DESIGN\n            elif group_id == GROUP_IDENTIFIERS[\"MASTER_COURSE_OTHER\"]:\n                return FieldOfStudyType.OTHER_MASTERS\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER\"],\n                GROUP_IDENTIFIERS[\"MASTER_OLD\"],\n            ):\n                found_master_study = True\n\n        # If we don't find a specific master study, return 'other'\n        if found_master_study:\n            return FieldOfStudyType.OTHER_MASTERS\n\n    # Return guest if we find nothing else\n    return FieldOfStudyType.GUEST\n", "path": "apps/dataporten/study/utils.py"}], "after_files": [{"content": "import logging\n\nfrom dateutil.parser import parse\nfrom django.utils import timezone\n\nfrom apps.authentication.constants import FieldOfStudyType\nfrom apps.dataporten.study.courses import GROUP_IDENTIFIERS, MASTER_IDS\n\nlogger = logging.getLogger(__name__)\n\n\ndef get_study(groups):\n    study_group = {}\n    for group in groups:\n        if group.get(\"id\") == GROUP_IDENTIFIERS[\"BACHELOR\"]:\n            logger.debug(\"User found to be bachelor student\")\n            study_group = group\n            break\n\n        elif group.get(\"id\") == GROUP_IDENTIFIERS[\"MASTER_OLD\"]:\n            logger.debug(\"User found to be master student on old programme\")\n            study_group = group\n            break\n\n        elif group.get(\"id\") == GROUP_IDENTIFIERS[\"MASTER\"]:\n            logger.debug(\"User found to be master student\")\n            study_group = group\n            break\n\n    return study_group\n\n\ndef get_group_id(group):\n    return group.get(\"id\", \"\")\n\n\ndef get_group_name(group):\n    return group.get(\"displayName\", \"\")\n\n\ndef get_course_finish_date(course):\n    if \"membership\" in course:\n        if \"notAfter\" in course[\"membership\"]:\n            # User has finished this course\n            raw_datetime = course.get(\"membership\", {}).get(\"notAfter\", \"\")\n            try:\n                # Date format: 2014-08-14T22:00:00Z\n                return parse(raw_datetime)\n            except ValueError:\n                logger.error('Failed to parse datetime \"%s\".' % raw_datetime)\n    return None\n\n\ndef get_add_years(course):\n    \"\"\"Add years back for more recent courses.\n        If course is 2nd grade, the user started one more year before.\"\"\"\n    # Add 1 year if verification happens during fall, 0 if during spring.\n    add_years = 1 if timezone.now().month >= 7 else 0\n\n    if course[\"id\"] == GROUP_IDENTIFIERS[\"PROSJEKT1\"]:\n        add_years += 1\n    elif course[\"id\"] == GROUP_IDENTIFIERS[\"ALGDAT\"]:\n        add_years += 1\n    elif course[\"id\"] == GROUP_IDENTIFIERS[\"PROSJEKT2\"]:\n        add_years += 3\n\n    return min(3, add_years)\n\n\ndef get_year_from_course(course, date):\n    return (timezone.now().year - date.year) + get_add_years(course)\n\n\ndef get_bachelor_year(groups):\n    years = []\n    for group in groups:\n        if group.get(\"id\") in GROUP_IDENTIFIERS.values():\n            logger.debug(\"Finding study year from {}\".format(group.get(\"id\")))\n            parsed_datetime = get_course_finish_date(group)\n            if parsed_datetime:\n                years.append(get_year_from_course(group, parsed_datetime))\n            else:\n                # If we don't know the end date, only add the years for the course.\n                years.append(get_add_years(group))\n\n    # Allows for users with extended bachelors to retain year 3 privileges.\n    return max(years) if max(years) <= 3 else 3\n\n\ndef get_master_year(groups):\n    for group in groups:\n        if group.get(\"id\") in MASTER_IDS:\n            logger.debug(\"Identified master study course: %s\" % group.get(\"id\"))\n            return 5\n    return 4\n\n\ndef get_year(study_id, groups):\n    if study_id == GROUP_IDENTIFIERS[\"BACHELOR\"]:\n        return get_bachelor_year(groups)\n    elif study_id == GROUP_IDENTIFIERS[\"MASTER\"]:\n        return get_master_year(groups)\n    else:\n        return 0\n\n\ndef get_field_of_study(groups):\n    if get_group_id(get_study(groups)) == GROUP_IDENTIFIERS[\"BACHELOR\"]:\n        return FieldOfStudyType.BACHELOR\n    else:\n        found_master_study = False\n        for group in groups:\n            group_id = get_group_id(group)\n            if group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_PVS_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_SWE\"],\n            ):\n                return FieldOfStudyType.SOFTWARE_ENGINEERING\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_DBS_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_DBS\"],\n            ):\n                return FieldOfStudyType.DATABASE_AND_SEARCH\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_KI_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_AI\"],\n            ):\n                return FieldOfStudyType.ARTIFICIAL_INTELLIGENCE\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_UX_OLD\"],\n                GROUP_IDENTIFIERS[\"MASTER_SPEC_UX\"],\n            ):\n                return FieldOfStudyType.INTERACTION_DESIGN\n            elif group_id == GROUP_IDENTIFIERS[\"MASTER_COURSE_OTHER\"]:\n                return FieldOfStudyType.OTHER_MASTERS\n            elif group_id in (\n                GROUP_IDENTIFIERS[\"MASTER\"],\n                GROUP_IDENTIFIERS[\"MASTER_OLD\"],\n            ):\n                found_master_study = True\n\n        # If we don't find a specific master study, return 'other'\n        if found_master_study:\n            return FieldOfStudyType.OTHER_MASTERS\n\n    # Return guest if we find nothing else\n    return FieldOfStudyType.GUEST\n", "path": "apps/dataporten/study/utils.py"}]}