Skip to content

Commit 93ec83a

Browse files
authored
✨ add to support for fr bank account details v2 (#149)
1 parent b6506c5 commit 93ec83a

File tree

10 files changed

+246
-2
lines changed

10 files changed

+246
-2
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from mindee import Client, documents
2+
3+
# Init a new client
4+
mindee_client = Client(api_key="my-api-key")
5+
6+
# Load a file from disk
7+
input_doc = mindee_client.doc_from_path("/path/to/the/file.ext")
8+
9+
# Parse the Bank Account Details by passing the appropriate type
10+
result = input_doc.parse(documents.fr.TypeBankAccountDetailsV2)
11+
12+
# Print a brief summary of the parsed data
13+
print(result.document)

docs/extras/code_samples/invoice_splitter_v1_async.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ mindee_client = Client(api_key="my-api-key")
88
input_doc = mindee_client.doc_from_path("/path/to/the/file.ext")
99

1010
# Put the document class in a local variable to keep the code DRY
11-
1211
doc_class = documents.TypeInvoiceSplitterV1
1312

1413
# Limit the amount of API calls to retrieve your document
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Bank Account Details V2
2+
-----------------------
3+
4+
**Sample Code:**
5+
6+
.. literalinclude:: /extras/code_samples/bank_account_details_v2.txt
7+
:language: Python
8+
9+
.. autoclass:: mindee.documents.fr.BankAccountDetailsV2
10+
:members:
11+
12+
.. autoclass:: mindee.documents.fr.BankAccountDetailsV2Bban
13+
:members:

docs/predictions/standard/fr.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ France
55
.. include:: ./documents/fr/carte_vitale_v1.rst
66
.. include:: ./documents/fr/carte_grise_v1.rst
77
.. include:: ./documents/fr/bank_account_details_v1.rst
8+
.. include:: ./documents/fr/bank_account_details_v2.rst

mindee/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,11 @@ def _init_default_endpoints(self) -> None:
444444
url_name="bank_account_details",
445445
version="1",
446446
),
447+
ConfigSpec(
448+
doc_class=documents.fr.BankAccountDetailsV2,
449+
url_name="bank_account_details",
450+
version="2",
451+
),
447452
ConfigSpec(
448453
doc_class=documents.eu.LicensePlateV1,
449454
url_name="license_plates",

mindee/documents/fr/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
BankAccountDetailsV1,
33
TypeBankAccountDetailsV1,
44
)
5+
from .bank_account_details.bank_account_details_v2 import (
6+
BankAccountDetailsV2,
7+
TypeBankAccountDetailsV2,
8+
)
59
from .carte_grise.carte_grise_v1 import CarteGriseV1, TypeCarteGriseV1
610
from .carte_vitale.carte_vitale_v1 import CarteVitaleV1, TypeCarteVitaleV1
711
from .id_card.id_card_v1 import IdCardV1, TypeIdCardV1
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
from typing import Optional, TypeVar
2+
3+
from mindee.documents.base import Document, TypeApiPrediction, clean_out_string
4+
from mindee.fields.text import TextField
5+
6+
from .bank_account_details_v2_bban import BankAccountDetailsV2Bban
7+
8+
9+
class BankAccountDetailsV2(Document):
10+
"""Bank Account Details v2 prediction results."""
11+
12+
account_holders_names: TextField
13+
"""Full extraction of the account holders names."""
14+
bban: BankAccountDetailsV2Bban
15+
"""Full extraction of BBAN, including: branch code, bank code, account and key."""
16+
iban: TextField
17+
"""Full extraction of the IBAN number."""
18+
swift_code: TextField
19+
"""Full extraction of the SWIFT code."""
20+
21+
def __init__(
22+
self,
23+
api_prediction=None,
24+
input_source=None,
25+
page_n: Optional[int] = None,
26+
):
27+
"""
28+
Bank Account Details v2 prediction results.
29+
30+
:param api_prediction: Raw prediction from HTTP response
31+
:param input_source: Input object
32+
:param page_n: Page number for multi pages pdf input
33+
"""
34+
super().__init__(
35+
input_source=input_source,
36+
document_type="bank_account_details",
37+
api_prediction=api_prediction,
38+
page_n=page_n,
39+
)
40+
self._build_from_api_prediction(api_prediction["prediction"], page_n=page_n)
41+
42+
def _build_from_api_prediction(
43+
self, api_prediction: TypeApiPrediction, page_n: Optional[int] = None
44+
) -> None:
45+
"""
46+
Build the object from the prediction API JSON.
47+
48+
:param api_prediction: Raw prediction from HTTP response
49+
:param page_n: Page number
50+
"""
51+
self.account_holders_names = TextField(
52+
api_prediction["account_holders_names"],
53+
page_id=page_n,
54+
)
55+
self.bban = BankAccountDetailsV2Bban(
56+
api_prediction["bban"],
57+
page_id=page_n,
58+
)
59+
self.iban = TextField(
60+
api_prediction["iban"],
61+
page_id=page_n,
62+
)
63+
self.swift_code = TextField(
64+
api_prediction["swift_code"],
65+
page_id=page_n,
66+
)
67+
68+
def __str__(self) -> str:
69+
return clean_out_string(
70+
"FR Bank Account Details V2 Prediction\n"
71+
"=====================================\n"
72+
f":Filename: {self.filename or ''}\n"
73+
f":Account Holder's Names: {self.account_holders_names}\n"
74+
f":Basic Bank Account Number:\n{self.bban.to_field_list()}\n"
75+
f":IBAN: {self.iban}\n"
76+
f":SWIFT Code: {self.swift_code}\n"
77+
)
78+
79+
80+
TypeBankAccountDetailsV2 = TypeVar(
81+
"TypeBankAccountDetailsV2", bound=BankAccountDetailsV2
82+
)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from typing import Dict, Optional
2+
3+
from mindee.fields.base import FieldConfidenceMixin, FieldPositionMixin, TypePrediction
4+
5+
6+
class BankAccountDetailsV2Bban(FieldPositionMixin, FieldConfidenceMixin):
7+
"""Full extraction of BBAN, including: branch code, bank code, account and key."""
8+
9+
bban_bank_code: Optional[str]
10+
"""The BBAN bank code outputted as a string."""
11+
bban_branch_code: Optional[str]
12+
"""The BBAN branch code outputted as a string."""
13+
bban_key: Optional[str]
14+
"""The BBAN key outputted as a string."""
15+
bban_number: Optional[str]
16+
"""The BBAN Account number outputted as a string."""
17+
page_n: int
18+
"""The document page on which the information was found."""
19+
20+
def __init__(
21+
self,
22+
prediction: TypePrediction,
23+
page_id: Optional[int] = None,
24+
):
25+
self._set_confidence(prediction)
26+
self._set_position(prediction)
27+
28+
if page_id is None:
29+
try:
30+
self.page_n = prediction["page_id"]
31+
except KeyError:
32+
pass
33+
else:
34+
self.page_n = page_id
35+
36+
self.bban_bank_code = prediction["bban_bank_code"]
37+
self.bban_branch_code = prediction["bban_branch_code"]
38+
self.bban_key = prediction["bban_key"]
39+
self.bban_number = prediction["bban_number"]
40+
41+
def _printable_values(self) -> Dict[str, str]:
42+
"""Return values for printing."""
43+
return {
44+
"bban_bank_code": self.bban_bank_code
45+
if self.bban_bank_code is not None
46+
else "",
47+
"bban_branch_code": self.bban_branch_code
48+
if self.bban_branch_code is not None
49+
else "",
50+
"bban_key": self.bban_key if self.bban_key is not None else "",
51+
"bban_number": self.bban_number if self.bban_number is not None else "",
52+
}
53+
54+
def to_field_list(self) -> str:
55+
"""Output the object in a format suitable for inclusion in an rST field list."""
56+
printable = self._printable_values()
57+
return (
58+
f" :Bank Code: {printable['bban_bank_code']}\n"
59+
f" :Branch Code: {printable['bban_branch_code']}\n"
60+
f" :Key: {printable['bban_key']}\n"
61+
f" :Account Number: {printable['bban_number']}"
62+
)
63+
64+
def __str__(self) -> str:
65+
"""Default string representation."""
66+
printable = self._printable_values()
67+
return (
68+
f"Bank Code: {printable['bban_bank_code']}, "
69+
f"Branch Code: {printable['bban_branch_code']}, "
70+
f"Key: {printable['bban_key']}, "
71+
f"Account Number: {printable['bban_number']}, "
72+
).strip()
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import json
2+
3+
import pytest
4+
5+
from mindee.documents.fr import BankAccountDetailsV2
6+
7+
FR_BANK_ACCOUNT_DETAILS_DATA_DIR = "./tests/data/fr/bank_account_details"
8+
FILE_PATH_FR_BANK_ACCOUNT_DETAILS_V2_COMPLETE = (
9+
f"{ FR_BANK_ACCOUNT_DETAILS_DATA_DIR }/response_v2/complete.json"
10+
)
11+
FILE_PATH_FR_BANK_ACCOUNT_DETAILS_V2_EMPTY = (
12+
f"{ FR_BANK_ACCOUNT_DETAILS_DATA_DIR }/response_v2/empty.json"
13+
)
14+
15+
16+
@pytest.fixture
17+
def bank_account_details_v2_doc() -> BankAccountDetailsV2:
18+
json_data = json.load(open(FILE_PATH_FR_BANK_ACCOUNT_DETAILS_V2_COMPLETE))
19+
return BankAccountDetailsV2(json_data["document"]["inference"], page_n=None)
20+
21+
22+
@pytest.fixture
23+
def bank_account_details_v2_doc_empty() -> BankAccountDetailsV2:
24+
json_data = json.load(open(FILE_PATH_FR_BANK_ACCOUNT_DETAILS_V2_EMPTY))
25+
return BankAccountDetailsV2(json_data["document"]["inference"], page_n=None)
26+
27+
28+
@pytest.fixture
29+
def bank_account_details_v2_page0():
30+
json_data = json.load(open(FILE_PATH_FR_BANK_ACCOUNT_DETAILS_V2_COMPLETE))
31+
return BankAccountDetailsV2(
32+
json_data["document"]["inference"]["pages"][0], page_n=0
33+
)
34+
35+
36+
def test_empty_doc_constructor(bank_account_details_v2_doc_empty):
37+
assert bank_account_details_v2_doc_empty.account_holders_names.value is None
38+
assert bank_account_details_v2_doc_empty.bban.bban_bank_code is None
39+
assert bank_account_details_v2_doc_empty.bban.bban_branch_code is None
40+
assert bank_account_details_v2_doc_empty.bban.bban_key is None
41+
assert bank_account_details_v2_doc_empty.bban.bban_number is None
42+
assert bank_account_details_v2_doc_empty.iban.value is None
43+
assert bank_account_details_v2_doc_empty.swift_code.value is None
44+
45+
46+
def test_doc_constructor(bank_account_details_v2_doc):
47+
file_path = f"{ FR_BANK_ACCOUNT_DETAILS_DATA_DIR }/response_v2/doc_to_string.rst"
48+
reference_str = open(file_path, "r", encoding="utf-8").read()
49+
assert str(bank_account_details_v2_doc) == reference_str
50+
51+
52+
def test_page0_constructor(bank_account_details_v2_page0):
53+
file_path = f"{ FR_BANK_ACCOUNT_DETAILS_DATA_DIR }/response_v2/page0_to_string.rst"
54+
reference_str = open(file_path, "r", encoding="utf-8").read()
55+
assert str(bank_account_details_v2_page0) == reference_str

0 commit comments

Comments
 (0)