Skip to content

Commit b157251

Browse files
✨ Add French carte grise v1 support (#118)
1 parent 8c7b27b commit b157251

File tree

12 files changed

+376
-2
lines changed

12 files changed

+376
-2
lines changed

docs/predictions/standard/fr.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
France
2+
======
3+
4+
Carte Grise
5+
-----------
6+
.. autoclass:: mindee.documents.fr.CarteGriseV1
7+
:members:
8+
:undoc-members:

docs/predictions/standard/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ Off the Shelf
66

77
./international
88
./us
9+
./fr
910
./field_types

mindee/cli.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class CommandConfig(Generic[TypeDoc]):
4242
help="US Bank Check",
4343
doc_class=documents.us.TypeBankCheckV1,
4444
),
45+
"fr-carte-grise": CommandConfig(
46+
help="French Carte Grise",
47+
doc_class=documents.fr.TypeCarteGriseV1,
48+
),
4549
}
4650

4751

mindee/client.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
)
1414
from mindee.documents.base import Document, TypeDocument
1515
from mindee.documents.config import DocumentConfig, DocumentConfigDict
16+
from mindee.documents.fr import CarteGriseV1
1617
from mindee.documents.us import BankCheckV1
1718
from mindee.endpoints import OTS_OWNER, CustomEndpoint, HTTPException, StandardEndpoint
1819
from mindee.input.page_options import PageOptions
@@ -257,6 +258,15 @@ def _init_default_endpoints(self) -> None:
257258
)
258259
],
259260
),
261+
(OTS_OWNER, CarteGriseV1.__name__): DocumentConfig(
262+
document_type="carte_grise_v1",
263+
document_class=CarteGriseV1,
264+
endpoints=[
265+
StandardEndpoint(
266+
url_name="carte_grise", version="1", api_key=self.api_key
267+
)
268+
],
269+
),
260270
(OTS_OWNER, CropperV1.__name__): DocumentConfig(
261271
document_type="cropper_v1",
262272
document_class=CropperV1,

mindee/documents/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from mindee.documents import us
1+
from mindee.documents import fr, us
22
from mindee.documents.cropper import CropperV1, TypeCropperV1
33
from mindee.documents.custom import CustomV1, TypeCustomV1
44
from mindee.documents.financial import FinancialV1, TypeFinancialV1

mindee/documents/fr/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .carte_grise.carte_grise_v1 import CarteGriseV1, TypeCarteGriseV1

mindee/documents/fr/carte_grise/__init__.py

Whitespace-only changes.
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
from typing import Optional, TypeVar
2+
3+
from mindee.documents.base import Document, TypeApiPrediction, clean_out_string
4+
from mindee.fields.date import DateField
5+
from mindee.fields.text import TextField
6+
7+
8+
class CarteGriseV1(Document):
9+
formula_number: TextField
10+
"""Document formula number"""
11+
mrz1: TextField
12+
"""Machine readable zone first line"""
13+
mrz2: TextField
14+
"""Machine readable zone second line"""
15+
owner_first_name: TextField
16+
"""Vehicle's owner first name"""
17+
owner_surname: TextField
18+
"""Vehicle's owner surname"""
19+
a: TextField
20+
"""Vehicle license plate number"""
21+
b: DateField
22+
"""Vehicle first release date"""
23+
c1: TextField
24+
"""Vehicle's owner full name including maiden name"""
25+
c3: TextField
26+
"""Vehicle's owner address"""
27+
c41: TextField
28+
"""Number of owners of the license certificate"""
29+
c4a: TextField
30+
"""Mention about the ownership of the vehicle"""
31+
d1: TextField
32+
"""Vehicle brand"""
33+
d3: TextField
34+
"""vehicle commercial name"""
35+
e: TextField
36+
"""Vehicle identification number (VIN)"""
37+
f1: TextField
38+
"""Vehicle's maximum admissible weight"""
39+
f2: TextField
40+
"""Vehicle's maximum admissible weight within the license's state"""
41+
f3: TextField
42+
"""Vehicle's maximum authorized weight with coupling"""
43+
g: TextField
44+
"""Vehicle's weight with coupling if tractor different than category M1"""
45+
g1: TextField
46+
"""Vehicle's national empty weight"""
47+
i: DateField
48+
"""Car registration date of the given certificate"""
49+
j: TextField
50+
"""Vehicle's category"""
51+
j1: TextField
52+
"""Vehicle's national type"""
53+
j2: TextField
54+
"""Vehicle's body type (CE)"""
55+
j3: TextField
56+
"""Vehicle's body type (National designation)"""
57+
p1: TextField
58+
"""Vehicle's displacement (cm3)"""
59+
p2: TextField
60+
"""Vehicle's maximum net power (kW)"""
61+
p3: TextField
62+
"""Vehicle's fuel type"""
63+
p6: TextField
64+
"""Vehicle's administrative power (fiscal horse power)"""
65+
q: TextField
66+
"""Vehicle's power / weight ratio"""
67+
s1: TextField
68+
"""Vehicle's number of seats"""
69+
s2: TextField
70+
"""Vehicle's number of standing rooms (person)"""
71+
u1: TextField
72+
"""Vehicle's sound level (dB)"""
73+
u2: TextField
74+
"""Vehicle's engine rotation speed (min-1)"""
75+
v7: TextField
76+
"""Vehicle's CO2 emission"""
77+
x1: DateField
78+
"""Next technical control date"""
79+
y1: TextField
80+
"""Amount of the regional proportional tax of the gray card (in euros)."""
81+
y2: TextField
82+
"""Amount of the additional parafiscal tax of the gray card (in euros)."""
83+
y3: TextField
84+
"""Amount of the additional CO2 tax of the gray card (in euros)."""
85+
y4: TextField
86+
"""Amount of the fee for managing the registration certificate (in euros)."""
87+
y5: TextField
88+
"""Amount of the fee for delivery of the registration certificate in euros."""
89+
y6: TextField
90+
"""Total amount of registration fee to be paid in euros."""
91+
92+
def __init__(
93+
self,
94+
api_prediction=None,
95+
input_source=None,
96+
page_n: Optional[int] = None,
97+
document_type="carte_grise",
98+
):
99+
"""
100+
Bank check document.
101+
102+
:param api_prediction: Raw prediction from HTTP response
103+
:param input_source: Input object
104+
:param page_n: Page number for multi pages pdf input
105+
"""
106+
super().__init__(
107+
input_source=input_source,
108+
document_type=document_type,
109+
api_prediction=api_prediction,
110+
page_n=page_n,
111+
)
112+
self._build_from_api_prediction(api_prediction["prediction"], page_n=page_n)
113+
114+
def _build_from_api_prediction(
115+
self, api_prediction: TypeApiPrediction, page_n: Optional[int] = None
116+
) -> None:
117+
"""
118+
Build the document from an API response JSON.
119+
120+
:param api_prediction: Raw prediction from HTTP response
121+
:param page_n: Page number for multi pages pdf input
122+
"""
123+
# pylint: disable=invalid-name
124+
self.formula_number = TextField(api_prediction["formula_number"], page_n=page_n)
125+
self.mrz1 = TextField(api_prediction["mrz1"], page_n=page_n)
126+
self.mrz2 = TextField(api_prediction["mrz2"], page_n=page_n)
127+
self.owner_first_name = TextField(
128+
api_prediction["owner_first_name"], page_n=page_n
129+
)
130+
self.owner_surname = TextField(api_prediction["owner_surname"], page_n=page_n)
131+
self.a = TextField(api_prediction["a"], page_n=page_n)
132+
self.b = DateField(api_prediction["b"], page_n=page_n)
133+
self.c1 = TextField(api_prediction["c1"], page_n=page_n)
134+
self.c3 = TextField(api_prediction["c3"], page_n=page_n)
135+
self.c41 = TextField(api_prediction["c41"], page_n=page_n)
136+
self.c4a = TextField(api_prediction["c4a"], page_n=page_n)
137+
self.d1 = TextField(api_prediction["d1"], page_n=page_n)
138+
self.d3 = TextField(api_prediction["d3"], page_n=page_n)
139+
self.e = TextField(api_prediction["e"], page_n=page_n)
140+
self.f1 = TextField(api_prediction["f1"], page_n=page_n)
141+
self.f2 = TextField(api_prediction["f2"], page_n=page_n)
142+
self.f3 = TextField(api_prediction["f3"], page_n=page_n)
143+
self.g = TextField(api_prediction["g"], page_n=page_n)
144+
self.g1 = TextField(api_prediction["g1"], page_n=page_n)
145+
self.i = DateField(api_prediction["i"], page_n=page_n)
146+
self.j = TextField(api_prediction["j"], page_n=page_n)
147+
self.j1 = TextField(api_prediction["j1"], page_n=page_n)
148+
self.j2 = TextField(api_prediction["j2"], page_n=page_n)
149+
self.j3 = TextField(api_prediction["j3"], page_n=page_n)
150+
self.p1 = TextField(api_prediction["p1"], page_n=page_n)
151+
self.p2 = TextField(api_prediction["p2"], page_n=page_n)
152+
self.p3 = TextField(api_prediction["p3"], page_n=page_n)
153+
self.p6 = TextField(api_prediction["p6"], page_n=page_n)
154+
self.q = TextField(api_prediction["q"], page_n=page_n)
155+
self.s1 = TextField(api_prediction["s1"], page_n=page_n)
156+
self.s2 = TextField(api_prediction["s2"], page_n=page_n)
157+
self.u1 = TextField(api_prediction["u1"], page_n=page_n)
158+
self.u2 = TextField(api_prediction["u2"], page_n=page_n)
159+
self.v7 = TextField(api_prediction["v7"], page_n=page_n)
160+
self.x1 = DateField(api_prediction["x1"], page_n=page_n)
161+
self.y1 = TextField(api_prediction["y1"], page_n=page_n)
162+
self.y2 = TextField(api_prediction["y2"], page_n=page_n)
163+
self.y3 = TextField(api_prediction["y3"], page_n=page_n)
164+
self.y4 = TextField(api_prediction["y4"], page_n=page_n)
165+
self.y5 = TextField(api_prediction["y5"], page_n=page_n)
166+
self.y6 = TextField(api_prediction["y6"], page_n=page_n)
167+
168+
def __str__(self) -> str:
169+
return clean_out_string(
170+
"----- FR Carte Grise V1 -----\n"
171+
f"Filename: {self.filename or ''}\n"
172+
f"formula_number: {self.formula_number}\n"
173+
f"mrz1: {self.mrz1}\n"
174+
f"mrz2: {self.mrz2}\n"
175+
f"owner_first_name: {self.owner_first_name}\n"
176+
f"owner_surname: {self.owner_surname}\n"
177+
f"a: {self.a}\n"
178+
f"b: {self.b}\n"
179+
f"c1: {self.c1}\n"
180+
f"c3: {self.c3}\n"
181+
f"c41: {self.c41}\n"
182+
f"c4a: {self.c4a}\n"
183+
f"d1: {self.d1}\n"
184+
f"d3: {self.d3}\n"
185+
f"e: {self.e}\n"
186+
f"f1: {self.f1}\n"
187+
f"f2: {self.f2}\n"
188+
f"f3: {self.f3}\n"
189+
f"g: {self.g}\n"
190+
f"g1: {self.g1}\n"
191+
f"i: {self.i}\n"
192+
f"j: {self.j}\n"
193+
f"j1: {self.j1}\n"
194+
f"j2: {self.j2}\n"
195+
f"j3: {self.j3}\n"
196+
f"p1: {self.p1}\n"
197+
f"p2: {self.p2}\n"
198+
f"p3: {self.p3}\n"
199+
f"p6: {self.p6}\n"
200+
f"q: {self.q}\n"
201+
f"s1: {self.s1}\n"
202+
f"s2: {self.s2}\n"
203+
f"u1: {self.u1}\n"
204+
f"u2: {self.u2}\n"
205+
f"v7: {self.v7}\n"
206+
f"x1: {self.x1}\n"
207+
f"y1: {self.y1}\n"
208+
f"y2: {self.y2}\n"
209+
f"y3: {self.y3}\n"
210+
f"y4: {self.y4}\n"
211+
f"y5: {self.y5}\n"
212+
f"y6: {self.y6}\n"
213+
"----------------------"
214+
)
215+
216+
def _checklist(self) -> None:
217+
pass
218+
219+
220+
TypeCarteGriseV1 = TypeVar("TypeCarteGriseV1", bound=CarteGriseV1)

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
INVOICE_DATA_DIR = "./tests/data/invoice"
33
PASSPORT_DATA_DIR = "./tests/data/passport"
44
US_BANK_CHECK_DATA_DIR = "./tests/data/us/bank_check"
5+
FR_CARTE_GRISE_DATA_DIR = "./tests/data/fr/carte_grise"
56
CUSTOM_DATA_DIR = "./tests/data/custom"
67
CROPPER_DATA_DIR = "./tests/data/cropper"
78
PDF_DATA_DIR = "./tests/data/pdf"

0 commit comments

Comments
 (0)