11from typing import List , Optional , TypeVar
22
33from mindee .documents .base import Document , TypeApiPrediction , clean_out_string
4- from mindee .documents .invoice .line_item_v4 import InvoiceLineItemV4
54from mindee .fields .amount import AmountField
65from mindee .fields .classification import ClassificationField
76from mindee .fields .company_registration import CompanyRegistrationField
1110from mindee .fields .tax import Taxes
1211from mindee .fields .text import TextField
1312
13+ from .financial_document_v1_line_item import FinancialDocumentV1LineItem
14+
1415
1516class FinancialDocumentV1 (Document ):
16- locale : LocaleField
17- """locale information"""
18- total_amount : AmountField
19- """Total including taxes"""
20- total_net : AmountField
21- """Total excluding taxes"""
17+ """Financial Document v1 prediction results."""
18+
19+ category : ClassificationField
20+ """The purchase category among predefined classes."""
21+ customer_address : TextField
22+ """The address of the customer."""
23+ customer_company_registrations : List [CompanyRegistrationField ]
24+ """List of company registrations associated to the customer."""
25+ customer_name : TextField
26+ """The name of the customer."""
2227 date : DateField
23- """Date the invoice was issued"""
28+ """The date the purchase was made."""
29+ document_type : ClassificationField
30+ """One of: 'INVOICE', 'CREDIT NOTE', 'CREDIT CARD RECEIPT', 'EXPENSE RECEIPT'."""
31+ due_date : DateField
32+ """The date on which the payment is due."""
2433 invoice_number : TextField
25- """Invoice number"""
34+ """The invoice number or identifier."""
35+ line_items : List [FinancialDocumentV1LineItem ]
36+ """List of line item details."""
37+ locale : LocaleField
38+ """The locale detected on the document."""
2639 reference_numbers : List [TextField ]
27- """List of Reference numbers including PO number."""
28- due_date : DateField
29- """Date the invoice is due"""
30- taxes : Taxes
31- """List of all taxes"""
32- total_tax : AmountField
33- """Sum total of all taxes"""
34- supplier_name : TextField
35- """Supplier 's name"""
40+ """List of Reference numbers, including PO number."""
41+ subcategory : ClassificationField
42+ """The purchase subcategory among predefined classes for transport and food."""
3643 supplier_address : TextField
37- """Supplier's address"""
44+ """The address of the supplier or merchant. """
3845 supplier_company_registrations : List [CompanyRegistrationField ]
39- """Company numbers"""
40- customer_name : TextField
41- """Customer's name"""
42- customer_address : TextField
43- """Customer's address"""
44- customer_company_registrations : List [CompanyRegistrationField ]
45- """Customer company registration numbers"""
46+ """List of company registrations associated to the supplier."""
47+ supplier_name : TextField
48+ """The name of the supplier or merchant."""
4649 supplier_payment_details : List [PaymentDetails ]
47- """Payment details"""
48- line_items : List [ InvoiceLineItemV4 ]
49- """Details of line items """
50- tip : AmountField
51- """Total amount of tip and gratuity ."""
50+ """List of payment details associated to the supplier. """
51+ supplier_phone_number : TextField
52+ """The phone number of the supplier or merchant. """
53+ taxes : Taxes
54+ """List of tax lines information ."""
5255 time : TextField
53- """Time as seen on the receipt in HH:MM format."""
54- document_type : ClassificationField
55- """A classification field, among predefined classes."""
56- category : ClassificationField
57- """The invoice or receipt category among predefined classes."""
58- subcategory : ClassificationField
59- """The invoice or receipt sub-category among predefined classes."""
56+ """The time the purchase was made."""
57+ tip : AmountField
58+ """The total amount of tip and gratuity"""
59+ total_amount : AmountField
60+ """The total amount paid: includes taxes, tips, fees, and other charges."""
61+ total_net : AmountField
62+ """The net amount paid: does not include taxes, fees, and discounts."""
63+ total_tax : AmountField
64+ """The total amount of taxes."""
6065
6166 def __init__ (
6267 self ,
@@ -65,18 +70,15 @@ def __init__(
6570 page_n : Optional [int ] = None ,
6671 ):
6772 """
68- Union of `Invoice` and `Receipt` .
73+ Financial Document v1 prediction results .
6974
7075 :param api_prediction: Raw prediction from HTTP response
7176 :param input_source: Input object
72- :param page_n: Page number for multi-page PDF input
77+ :param page_n: Page number for multi pages pdf input
7378 """
74- # need this for building from prediction
75- self .input_file = input_source
76-
7779 super ().__init__ (
7880 input_source = input_source ,
79- document_type = "financial_doc " ,
81+ document_type = "financial_document " ,
8082 api_prediction = api_prediction ,
8183 page_n = page_n ,
8284 )
@@ -86,115 +88,175 @@ def _build_from_api_prediction(
8688 self , api_prediction : TypeApiPrediction , page_n : Optional [int ] = None
8789 ) -> None :
8890 """
89- Build the document from an API response JSON.
91+ Build the object from the prediction API JSON.
9092
9193 :param api_prediction: Raw prediction from HTTP response
92- :param page_n: Page number for multi pages pdf input
94+ :param page_n: Page number
9395 """
94- self .supplier_company_registrations = [
95- CompanyRegistrationField (field_dict , page_n = page_n )
96- for field_dict in api_prediction ["supplier_company_registrations" ]
96+ self .category = ClassificationField (
97+ api_prediction ["category" ],
98+ page_id = page_n ,
99+ )
100+ self .customer_address = TextField (
101+ api_prediction ["customer_address" ],
102+ page_id = page_n ,
103+ )
104+ self .customer_company_registrations = [
105+ CompanyRegistrationField (prediction , page_id = page_n )
106+ for prediction in api_prediction ["customer_company_registrations" ]
97107 ]
98- self .date = DateField (api_prediction ["date" ], page_n = page_n )
99- self .due_date = DateField (api_prediction ["due_date" ], page_n = page_n )
100- self .invoice_number = TextField (api_prediction ["invoice_number" ], page_n = page_n )
101- self .reference_numbers = [
102- TextField (reference_number , page_n = page_n )
103- for reference_number in api_prediction ["reference_numbers" ]
108+ self .customer_name = TextField (
109+ api_prediction ["customer_name" ],
110+ page_id = page_n ,
111+ )
112+ self .date = DateField (
113+ api_prediction ["date" ],
114+ page_id = page_n ,
115+ )
116+ self .document_type = ClassificationField (
117+ api_prediction ["document_type" ],
118+ page_id = page_n ,
119+ )
120+ self .due_date = DateField (
121+ api_prediction ["due_date" ],
122+ page_id = page_n ,
123+ )
124+ self .invoice_number = TextField (
125+ api_prediction ["invoice_number" ],
126+ page_id = page_n ,
127+ )
128+ self .line_items = [
129+ FinancialDocumentV1LineItem (prediction , page_id = page_n )
130+ for prediction in api_prediction ["line_items" ]
104131 ]
105132 self .locale = LocaleField (
106- api_prediction ["locale" ], value_key = "language" , page_n = page_n
133+ api_prediction ["locale" ],
134+ page_id = page_n ,
135+ )
136+ self .reference_numbers = [
137+ TextField (prediction , page_id = page_n )
138+ for prediction in api_prediction ["reference_numbers" ]
139+ ]
140+ self .subcategory = ClassificationField (
141+ api_prediction ["subcategory" ],
142+ page_id = page_n ,
107143 )
108- self .supplier_name = TextField (api_prediction ["supplier_name" ], page_n = page_n )
109144 self .supplier_address = TextField (
110- api_prediction ["supplier_address" ], page_n = page_n
145+ api_prediction ["supplier_address" ],
146+ page_id = page_n ,
111147 )
112- self .customer_name = TextField (api_prediction ["customer_name" ], page_n = page_n )
113- self .customer_company_registrations = [
114- CompanyRegistrationField (field_dict , page_n = page_n )
115- for field_dict in api_prediction ["customer_company_registrations" ]
148+ self .supplier_company_registrations = [
149+ CompanyRegistrationField (prediction , page_id = page_n )
150+ for prediction in api_prediction ["supplier_company_registrations" ]
116151 ]
117- self .customer_address = TextField (
118- api_prediction ["customer_address" ], page_n = page_n
152+ self .supplier_name = TextField (
153+ api_prediction ["supplier_name" ],
154+ page_id = page_n ,
119155 )
120- self .taxes = Taxes (api_prediction ["taxes" ], page_id = page_n )
121156 self .supplier_payment_details = [
122- PaymentDetails (payment_detail , page_n = page_n )
123- for payment_detail in api_prediction ["supplier_payment_details" ]
124- ]
125- self .line_items = [
126- InvoiceLineItemV4 (prediction = line_item , page_n = page_n )
127- for line_item in api_prediction ["line_items" ]
157+ PaymentDetails (prediction , page_id = page_n )
158+ for prediction in api_prediction ["supplier_payment_details" ]
128159 ]
129- self .total_amount = AmountField (api_prediction ["total_amount" ], page_n = page_n )
130- self .total_net = AmountField (api_prediction ["total_net" ], page_n = page_n )
131- self .total_tax = AmountField (api_prediction ["total_tax" ], page_n = page_n )
132- self .tip = AmountField (api_prediction ["tip" ], page_n = page_n )
133- self .time = TextField (api_prediction ["time" ], page_n = page_n )
134- self .document_type = ClassificationField (
135- api_prediction ["document_type" ], page_n = page_n
160+ self .supplier_phone_number = TextField (
161+ api_prediction ["supplier_phone_number" ],
162+ page_id = page_n ,
136163 )
137- self .category = ClassificationField (api_prediction ["category" ], page_n = page_n )
138- self .subcategory = ClassificationField (
139- api_prediction ["subcategory" ], page_n = page_n
164+ self .taxes = Taxes (api_prediction ["taxes" ], page_id = page_n )
165+ self .time = TextField (
166+ api_prediction ["time" ],
167+ page_id = page_n ,
168+ )
169+ self .tip = AmountField (
170+ api_prediction ["tip" ],
171+ page_id = page_n ,
172+ )
173+ self .total_amount = AmountField (
174+ api_prediction ["total_amount" ],
175+ page_id = page_n ,
176+ )
177+ self .total_net = AmountField (
178+ api_prediction ["total_net" ],
179+ page_id = page_n ,
180+ )
181+ self .total_tax = AmountField (
182+ api_prediction ["total_tax" ],
183+ page_id = page_n ,
140184 )
141185
142186 @staticmethod
143- def _line_items_separator (char : str ):
187+ def _line_items_separator (char : str ) -> str :
144188 out_str = " "
145189 out_str += f"+{ char * 38 } "
190+ out_str += f"+{ char * 14 } "
146191 out_str += f"+{ char * 10 } "
192+ out_str += f"+{ char * 12 } "
193+ out_str += f"+{ char * 14 } "
147194 out_str += f"+{ char * 14 } "
148195 out_str += f"+{ char * 12 } "
149196 return out_str + "+"
150197
198+ def _line_items_to_str (self ) -> str :
199+ if not self .line_items :
200+ return ""
201+
202+ lines = f"\n { self ._line_items_separator ('-' )} \n " .join (
203+ [item .to_table_line () for item in self .line_items ]
204+ )
205+ out_str = ""
206+ out_str += f"\n { self ._line_items_separator ('-' )} \n "
207+ out_str += " | Description "
208+ out_str += " | Product code"
209+ out_str += " | Quantity"
210+ out_str += " | Tax Amount"
211+ out_str += " | Tax Rate (%)"
212+ out_str += " | Total Amount"
213+ out_str += " | Unit Price"
214+ out_str += f" |\n { self ._line_items_separator ('=' )} "
215+ out_str += f"\n { lines } "
216+ out_str += f"\n { self ._line_items_separator ('-' )} "
217+ return out_str
218+
151219 def __str__ (self ) -> str :
152- supplier_company_registrations = "; " .join (
153- [str (n . value ) for n in self .supplier_company_registrations ]
220+ customer_company_registrations = f" \n { ' ' * 31 } " .join (
221+ [str (item ) for item in self .customer_company_registrations ],
154222 )
155- customer_company_registrations = "; " .join (
156- [str (n . value ) for n in self .customer_company_registrations ]
223+ reference_numbers = f" \n { ' ' * 18 } " .join (
224+ [str (item ) for item in self .reference_numbers ],
157225 )
158- reference_numbers = ", " .join ([str (n .value ) for n in self .reference_numbers ])
159- payment_details = "\n " .join (
160- [str (p ) for p in self .supplier_payment_details ]
226+ supplier_company_registrations = f"\n { ' ' * 31 } " .join (
227+ [str (item ) for item in self .supplier_company_registrations ],
228+ )
229+ supplier_payment_details = f"\n { ' ' * 25 } " .join (
230+ [str (item ) for item in self .supplier_payment_details ],
161231 )
162- line_items = "\n "
163- if self .line_items :
164- line_items = "\n Code | QTY | Price | Amount | Tax (Rate) | Description\n "
165- for item in self .line_items :
166- line_items += f" { item } \n "
167-
168232 return clean_out_string (
169233 "Financial Document V1 Prediction\n "
170234 "================================\n "
171235 f":Filename: { self .filename or '' } \n "
172- f":Document type: { self .document_type } \n "
173- f":Category: { self .category } \n "
174- f":Subcategory: { self .subcategory } \n "
175236 f":Locale: { self .locale } \n "
176- f":Invoice number: { self .invoice_number } \n "
177- f":Reference numbers: { reference_numbers } \n "
178- f":Date: { self .date } \n "
179- f":Due date: { self .due_date } \n "
180- f":Time: { self .time } \n "
237+ f":Invoice Number: { self .invoice_number } \n "
238+ f":Reference Numbers: { reference_numbers } \n "
239+ f":Purchase Date: { self .date } \n "
240+ f":Due Date: { self .due_date } \n "
241+ f":Total Net: { self .total_net } \n "
242+ f":Total Amount: { self .total_amount } \n "
243+ f":Taxes: { self .taxes } \n "
244+ f":Supplier Payment Details: { supplier_payment_details } \n "
181245 f":Supplier name: { self .supplier_name } \n "
182- f":Supplier address : { self . supplier_address } \n "
183- f":Supplier company registrations : { supplier_company_registrations } \n "
184- f":Supplier payment details : { payment_details } \n "
246+ f":Supplier Company Registrations : { supplier_company_registrations } \n "
247+ f":Supplier Address : { self . supplier_address } \n "
248+ f":Supplier Phone Number : { self . supplier_phone_number } \n "
185249 f":Customer name: { self .customer_name } \n "
186- f":Customer address: { self .customer_address } \n "
187- f":Customer company registrations: { customer_company_registrations } \n "
188- f":Tip: { self .tip } \n "
189- f":Taxes: { self .taxes } \n "
190- f":Total tax: { self .total_tax } \n "
191- f":Total net: { self .total_net } \n "
192- f":Total amount: { self .total_amount } \n "
193- f":Line Items: { line_items } "
250+ f":Customer Company Registrations: { customer_company_registrations } \n "
251+ f":Customer Address: { self .customer_address } \n "
252+ f":Document Type: { self .document_type } \n "
253+ f":Purchase Subcategory: { self .subcategory } \n "
254+ f":Purchase Category: { self .category } \n "
255+ f":Total Tax: { self .total_tax } \n "
256+ f":Tip and Gratuity: { self .tip } \n "
257+ f":Purchase Time: { self .time } \n "
258+ f":Line Items: { self ._line_items_to_str ()} \n "
194259 )
195260
196- def _checklist (self ) -> None :
197- pass
198-
199261
200262TypeFinancialDocumentV1 = TypeVar ("TypeFinancialDocumentV1" , bound = FinancialDocumentV1 )
0 commit comments