Skip to content

Commit 6187fbe

Browse files
✨ add support for us w9
1 parent 71fbd87 commit 6187fbe

File tree

10 files changed

+216
-2
lines changed

10 files changed

+216
-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 US W9 by passing the appropriate type
10+
result = input_doc.parse(documents.us.TypeW9V1)
11+
12+
# Print a brief summary of the parsed data
13+
print("\n".join([str(page) for page in result.pages]))
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
W9 V1
2+
-----
3+
4+
**Sample Code:**
5+
6+
.. literalinclude:: /extras/code_samples/us_w9_v1.txt
7+
:language: Python
8+
9+
.. autoclass:: mindee.documents.us.W9V1
10+
:members:

mindee/cli.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ class CommandConfig(Generic[TypeDoc]):
5151
help="US Bank Check",
5252
doc_class=documents.us.TypeBankCheckV1,
5353
),
54+
"us-w9": CommandConfig(
55+
help="US W9",
56+
doc_class=documents.us.TypeW9V1,
57+
),
5458
"eu-license-plate": CommandConfig(
5559
help="EU License Plate",
5660
doc_class=documents.eu.TypeLicensePlateV1,

mindee/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,11 @@ def _init_default_endpoints(self) -> None:
469469
url_name="material_certificate",
470470
version="1",
471471
),
472+
ConfigSpec(
473+
doc_class=documents.us.W9V1,
474+
url_name="us_w9",
475+
version="1",
476+
),
472477
]
473478

474479
for config in configs:

mindee/documents/us/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from .bank_check.bank_check_v1 import BankCheckV1, TypeBankCheckV1
2+
from .w9.w9_v1 import W9V1, TypeW9V1

mindee/documents/us/w9/__init__.py

Whitespace-only changes.

mindee/documents/us/w9/w9_v1.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
from typing import Optional, TypeVar
2+
3+
from mindee.documents.base import Document, TypeApiPrediction, clean_out_string
4+
from mindee.fields.position import PositionField
5+
from mindee.fields.text import TextField
6+
7+
8+
class W9V1(Document):
9+
"""US W9 v1 prediction results."""
10+
11+
address: TextField
12+
"""The street address (number, street, and apt. or suite no.) of the applicant."""
13+
business_name: TextField
14+
"""The business name or disregarded entity name, if different from Name."""
15+
city_state_zip: TextField
16+
"""The city, state, and ZIP code of the applicant."""
17+
ein: TextField
18+
"""The employer identification number."""
19+
name: TextField
20+
"""Name as shown on the applicant's income tax return."""
21+
signature_date_position: PositionField
22+
"""Position of the signature date on the document."""
23+
signature_position: PositionField
24+
"""Position of the signature on the document."""
25+
ssn: TextField
26+
"""The applicant's social security number."""
27+
tax_classification: TextField
28+
"""The federal tax classification, which can vary depending on the revision date."""
29+
tax_classification_llc: TextField
30+
"""Depending on revision year, among S, C, P or D for Limited Liability Company Classification."""
31+
tax_classif_other_details: TextField
32+
"""Tax Classification Other Details."""
33+
w9_revision_date: TextField
34+
"""The Revision month and year of the W9 form."""
35+
36+
def __init__(
37+
self,
38+
api_prediction=None,
39+
input_source=None,
40+
page_n: Optional[int] = None,
41+
):
42+
"""
43+
US W9 v1 prediction results.
44+
45+
:param api_prediction: Raw prediction from HTTP response
46+
:param input_source: Input object
47+
:param page_n: Page number for multi pages pdf input
48+
"""
49+
super().__init__(
50+
input_source=input_source,
51+
document_type="w9",
52+
api_prediction=api_prediction,
53+
page_n=page_n,
54+
)
55+
self._build_from_api_prediction(api_prediction["prediction"], page_n=page_n)
56+
57+
def _build_from_api_prediction(
58+
self, api_prediction: TypeApiPrediction, page_n: Optional[int] = None
59+
) -> None:
60+
"""
61+
Build the object from the prediction API JSON.
62+
63+
:param api_prediction: Raw prediction from HTTP response
64+
:param page_n: Page number
65+
"""
66+
self.address = TextField(
67+
api_prediction.get("address", {}),
68+
page_id=page_n,
69+
)
70+
self.business_name = TextField(
71+
api_prediction.get("business_name", {}),
72+
page_id=page_n,
73+
)
74+
self.city_state_zip = TextField(
75+
api_prediction.get("city_state_zip", {}),
76+
page_id=page_n,
77+
)
78+
self.ein = TextField(
79+
api_prediction.get("ein", {}),
80+
page_id=page_n,
81+
)
82+
self.name = TextField(
83+
api_prediction.get("name", {}),
84+
page_id=page_n,
85+
)
86+
self.signature_date_position = PositionField(
87+
api_prediction.get("signature_date_position", {}),
88+
page_id=page_n,
89+
)
90+
self.signature_position = PositionField(
91+
api_prediction.get("signature_position", {}),
92+
page_id=page_n,
93+
)
94+
self.ssn = TextField(
95+
api_prediction.get("ssn", {}),
96+
page_id=page_n,
97+
)
98+
self.tax_classification = TextField(
99+
api_prediction.get("tax_classification", {}),
100+
page_id=page_n,
101+
)
102+
self.tax_classification_llc = TextField(
103+
api_prediction.get("tax_classification_llc", {}),
104+
page_id=page_n,
105+
)
106+
self.tax_classif_other_details = TextField(
107+
api_prediction.get("tax_classification_other_details", {}),
108+
page_id=page_n,
109+
)
110+
self.w9_revision_date = TextField(
111+
api_prediction.get("w9_revision_date", {}),
112+
page_id=page_n,
113+
)
114+
115+
def __str__(self) -> str:
116+
return clean_out_string(
117+
"US W9 V1 Prediction\n"
118+
"======================\n"
119+
f":Filename: {self.filename or ''}\n"
120+
f":Name: {self.name}\n"
121+
f":SSN: {self.ssn}\n"
122+
f":Address: {self.address}\n"
123+
f":City State Zip: {self.city_state_zip}\n"
124+
f":Business Name: {self.business_name}\n"
125+
f":EIN: {self.ein}\n"
126+
f":Tax Classification: {self.tax_classification}\n"
127+
f":Tax Classification Other Details: {self.tax_classif_other_details}\n"
128+
f":W9 Revision Date: {self.w9_revision_date}\n"
129+
f":Signature Position: {self.signature_position}\n"
130+
f":Signature Date Position: {self.signature_date_position}\n"
131+
f":Tax Classification LLC: {self.tax_classification_llc}\n"
132+
)
133+
134+
135+
TypeW9V1 = TypeVar(
136+
"TypeW9V1",
137+
bound=W9V1,
138+
)

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[metadata]
22
name = mindee
33
author = Mindee
4-
author_email = devrel@mindee.com
4+
author_email = opensource@mindee.com
55
description = Mindee API helper library for Python
66
long_description = file:README.md
77
long_description_content_type = text/markdown

tests/documents/us/test_w9_v1.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import json
2+
3+
import pytest
4+
5+
from mindee.documents.us import W9V1
6+
7+
US_W9_DATA_DIR = "./tests/data/products/us_w9"
8+
FILE_PATH_US_W9_V1_COMPLETE = f"{ US_W9_DATA_DIR }/response_v1/complete.json"
9+
FILE_PATH_US_W9_V1_EMPTY = f"{ US_W9_DATA_DIR }/response_v1/empty.json"
10+
11+
12+
@pytest.fixture
13+
def w9_v1_doc() -> W9V1:
14+
json_data = json.load(open(FILE_PATH_US_W9_V1_COMPLETE, encoding="utf-8"))
15+
return W9V1(json_data["document"]["inference"], page_n=None)
16+
17+
18+
@pytest.fixture
19+
def w9_v1_doc_empty() -> W9V1:
20+
json_data = json.load(open(FILE_PATH_US_W9_V1_EMPTY, encoding="utf-8"))
21+
return W9V1(json_data["document"]["inference"], page_n=None)
22+
23+
24+
@pytest.fixture
25+
def w9_v1_page0():
26+
json_data = json.load(open(FILE_PATH_US_W9_V1_COMPLETE, encoding="utf-8"))
27+
return W9V1(json_data["document"]["inference"]["pages"][0], page_n=0)
28+
29+
30+
def test_empty_doc_constructor(w9_v1_doc_empty):
31+
assert w9_v1_doc_empty.name.value is None
32+
assert w9_v1_doc_empty.ssn.value is None
33+
assert w9_v1_doc_empty.address.value is None
34+
assert w9_v1_doc_empty.city_state_zip.value is None
35+
assert w9_v1_doc_empty.business_name.value is None
36+
assert w9_v1_doc_empty.ein.value is None
37+
assert w9_v1_doc_empty.tax_classification.value is None
38+
assert w9_v1_doc_empty.tax_classif_other_details.value is None
39+
assert w9_v1_doc_empty.w9_revision_date.value is None
40+
assert w9_v1_doc_empty.signature_position.value is None
41+
assert w9_v1_doc_empty.signature_date_position.value is None
42+
assert w9_v1_doc_empty.tax_classification_llc.value is None
43+

0 commit comments

Comments
 (0)