Repository: fabiocaccamo/python-codicefiscale

Issue:
Unactive municipalities cannot be retrieved
**Python version**
3.9.9

**Package version**
0.4.0

**Current behavior (bug description)**
Decoding does not work for inactive municipalities, since only active ones are considered in
```
for municipality in municipalities:
   if not municipality["active"]:
      continue
```

**Expected behavior**
inactive municipalities data should be considered.
When multiple entries are available, take the one  where  **birthday** falls within **date_created** and **date_deleted**


Discussion:
fabiocaccamo: @danisana thank you for this PR, I will review it as soon as possible.
codecov[bot]: # [Codecov](https://codecov.io/gh/fabiocaccamo/python-codicefiscale/pull/24?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo) Report
Base: **100.00**% // Head: **100.00**% // No change to project coverage :thumbsup:
> Coverage data is based on head [(`9dc83a7`)](https://codecov.io/gh/fabiocaccamo/python-codicefiscale/pull/24?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo) compared to base [(`4d83225`)](https://codecov.io/gh/fabiocaccamo/python-codicefiscale/commit/4d83225b38a61d3268f1c2ef7e543e7ce1068c70?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo).
> Patch coverage: 100.00% of modified lines in pull request are covered.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff            @@
##            master       #24   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            2         2           
  Lines          185       203   +18     
=========================================
+ Hits           185       203   +18     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `100.00% <100.00%> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/fabiocaccamo/python-codicefiscale/pull/24?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo) | Coverage Δ | |
|---|---|---|
| [codicefiscale/codicefiscale.py](https://codecov.io/gh/fabiocaccamo/python-codicefiscale/pull/24/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo#diff-Y29kaWNlZmlzY2FsZS9jb2RpY2VmaXNjYWxlLnB5) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/fabiocaccamo/python-codicefiscale/pull/24?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Fabio+Caccamo).


Patch:
diff --git a/codicefiscale/codicefiscale.py b/codicefiscale/codicefiscale.py
index 5b0ddc7..0539705 100644
--- a/codicefiscale/codicefiscale.py
+++ b/codicefiscale/codicefiscale.py
@@ -90,28 +90,24 @@ def _get_indexed_data():
     }
 
     for municipality in municipalities:
-        if not municipality["active"]:
-            continue
         code = municipality["code"]
         province = municipality["province"].lower()
         names = municipality["name_slugs"]
         for name in names:
             data["municipalities"][name] = municipality
             data["municipalities"][name + "-" + province] = municipality
-        assert (
-            code not in data["codes"]
-        ), "Found more than one country/municipality with the same code, expected a one-to-one relation."
-        data["codes"][code] = municipality
+        if code not in data["codes"]:
+            data["codes"][code] = []
+        data["codes"][code].append(municipality)
 
     for country in countries:
         code = country["code"]
         names = country["name_slugs"]
         for name in names:
             data["countries"][name] = country
-        assert (
-            code not in data["codes"]
-        ), "Found more than one country/municipality with the same code, expected a one-to-one relation."
-        data["codes"][code] = country
+        if code not in data["codes"]:
+            data["codes"][code] = []
+        data["codes"][code].append(country)
 
     return data
 
@@ -262,10 +258,14 @@ def encode_birthplace(birthplace):
         birthplace_data = _DATA["municipalities"].get(
             birthplace_slug,
             _DATA["countries"].get(
-                birthplace_slug, _DATA["codes"].get(birthplace_code, {})
+                birthplace_slug
             ),
         )
-        return birthplace_data.get("code", "")
+        if birthplace_data:
+            return birthplace_data.get("code", "")
+        if birthplace_code in _DATA["codes"]:
+            return birthplace_code
+        return ""
 
     birthplace_code = find_birthplace_code(birthplace) or find_birthplace_code(
         re.split(r",|\(", birthplace)[0]
@@ -409,9 +409,22 @@ def decode(code):
     except ValueError:
         raise ValueError(f"[codicefiscale] invalid date: {birthdate_str}")
 
-    birthplace = _DATA["codes"].get(
-        raw["birthplace"][0] + raw["birthplace"][1:].translate(_OMOCODIA_DECODE_TRANS)
-    )
+    codes = _DATA["codes"].get(raw["birthplace"][0] + raw["birthplace"][1:].translate(_OMOCODIA_DECODE_TRANS))
+    birthplace = None
+    for c in codes:
+        date_created = datetime.min
+        try:
+            date_created = datetime.strptime(c['date_created'], "%Y-%m-%d")
+        except ValueError:
+            date_created = datetime.min
+
+        try:
+            date_deleted = datetime.strptime(c['date_deleted'], "%Y-%m-%d")
+        except ValueError:
+            date_deleted = datetime.max
+        if date_created <= birthdate and date_deleted >= birthdate:
+            birthplace = c
+            break
 
     cin = raw["cin"]
     cin_check = encode_cin(code)


Test patch:
diff --git a/tests/tests.py b/tests/tests.py
index 750c0f8..2431241 100644
--- a/tests/tests.py
+++ b/tests/tests.py
@@ -436,15 +436,21 @@ class CodiceFiscaleTestCase(unittest.TestCase):
                 "input": "RSSMRA68A01H501Y",
                 "result": {"sex": "M", "birthdate": "01/01/1968", "birthplace": "Roma"},
             },
+            {
+                "input": "RSSMRA50B17A558W",
+                "result": {
+                    "sex": "M",
+                    "birthdate": "17/02/1950",
+                    "birthplace": "Porretta Terme",
+                },
+            },
         ]
 
         for obj in data:
             # with self.subTest(obj=obj):
-
             result = obj["result"]
             obj_decoded = codicefiscale.decode(obj["input"])
             #  print(obj_decoded)
-
             sex = obj_decoded.get("sex")
             self.assertFalse(sex is None)
             self.assertEqual(sex, result["sex"])