diff --git a/docs/extras/code_samples/bill_of_lading_v1_async.txt b/docs/extras/code_samples/bill_of_lading_v1_async.txt new file mode 100644 index 00000000..9d5ec6b6 --- /dev/null +++ b/docs/extras/code_samples/bill_of_lading_v1_async.txt @@ -0,0 +1,16 @@ +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.BillOfLadingV1, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) diff --git a/docs/extras/code_samples/energy_bill_fra_v1_async.txt b/docs/extras/code_samples/energy_bill_fra_v1_async.txt new file mode 100644 index 00000000..b5454a74 --- /dev/null +++ b/docs/extras/code_samples/energy_bill_fra_v1_async.txt @@ -0,0 +1,16 @@ +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.fr.EnergyBillV1, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) diff --git a/docs/extras/code_samples/nutrition_facts_v1_async.txt b/docs/extras/code_samples/nutrition_facts_v1_async.txt new file mode 100644 index 00000000..de0f1285 --- /dev/null +++ b/docs/extras/code_samples/nutrition_facts_v1_async.txt @@ -0,0 +1,16 @@ +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.NutritionFactsLabelV1, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) diff --git a/docs/extras/code_samples/payslip_fra_v2_async.txt b/docs/extras/code_samples/payslip_fra_v2_async.txt new file mode 100644 index 00000000..1e622121 --- /dev/null +++ b/docs/extras/code_samples/payslip_fra_v2_async.txt @@ -0,0 +1,16 @@ +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.fr.PayslipV2, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) diff --git a/docs/extras/code_samples/us_mail_v2_async.txt b/docs/extras/code_samples/us_mail_v2_async.txt new file mode 100644 index 00000000..52e12f67 --- /dev/null +++ b/docs/extras/code_samples/us_mail_v2_async.txt @@ -0,0 +1,16 @@ +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.us.UsMailV2, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) diff --git a/docs/extras/guide/bill_of_lading_v1.md b/docs/extras/guide/bill_of_lading_v1.md new file mode 100644 index 00000000..e42bd0e2 --- /dev/null +++ b/docs/extras/guide/bill_of_lading_v1.md @@ -0,0 +1,200 @@ +--- +title: Bill of Lading OCR Python +category: 622b805aaec68102ea7fcbc2 +slug: python-bill-of-lading-ocr +parentDoc: 609808f773b0b90051d839de +--- +The Python OCR SDK supports the [Bill of Lading API](https://platform.mindee.com/mindee/bill_of_lading). + +The [sample below](https://github.com/mindee/client-lib-test-data/blob/main/products/bill_of_lading/default_sample.jpg) can be used for testing purposes. +![Bill of Lading sample](https://github.com/mindee/client-lib-test-data/blob/main/products/bill_of_lading/default_sample.jpg?raw=true) + +# Quick-Start +```py +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.BillOfLadingV1, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) + +``` +# Field Types +## Standard Fields +These fields are generic and used in several products. + +### BaseField +Each prediction object contains a set of fields that inherit from the generic `BaseField` class. +A typical `BaseField` object will have the following attributes: + +* **value** (`Union[float, str]`): corresponds to the field value. Can be `None` if no value was extracted. +* **confidence** (`float`): the confidence score of the field prediction. +* **bounding_box** (`[Point, Point, Point, Point]`): contains exactly 4 relative vertices (points) coordinates of a right rectangle containing the field in the document. +* **polygon** (`List[Point]`): contains the relative vertices coordinates (`Point`) of a polygon containing the field in the image. +* **page_id** (`int`): the ID of the page, always `None` when at document-level. +* **reconstructed** (`bool`): indicates whether an object was reconstructed (not extracted as the API gave it). + +> **Note:** A `Point` simply refers to a List of two numbers (`[float, float]`). + + +Aside from the previous attributes, all basic fields have access to a custom `__str__` method that can be used to print their value as a string. + +### DateField +Aside from the basic `BaseField` attributes, the date field `DateField` also implements the following: + +* **date_object** (`Date`): an accessible representation of the value as a python object. Can be `None`. + +### StringField +The text field `StringField` only has one constraint: its **value** is an `Optional[str]`. + +## Specific Fields +Fields which are specific to this product; they are not used in any other product. + +### Carrier Field +The shipping company responsible for transporting the goods. + +A `BillOfLadingV1Carrier` implements the following attributes: + +* **name** (`str`): The name of the carrier. +* **professional_number** (`str`): The professional number of the carrier. +* **scac** (`str`): The Standard Carrier Alpha Code (SCAC) of the carrier. +Fields which are specific to this product; they are not used in any other product. + +### Consignee Field +The party to whom the goods are being shipped. + +A `BillOfLadingV1Consignee` implements the following attributes: + +* **address** (`str`): The address of the consignee. +* **email** (`str`): The email of the shipper. +* **name** (`str`): The name of the consignee. +* **phone** (`str`): The phone number of the consignee. +Fields which are specific to this product; they are not used in any other product. + +### Items Field +The goods being shipped. + +A `BillOfLadingV1CarrierItem` implements the following attributes: + +* **description** (`str`): A description of the item. +* **gross_weight** (`float`): The gross weight of the item. +* **measurement** (`float`): The measurement of the item. +* **measurement_unit** (`str`): The unit of measurement for the measurement. +* **quantity** (`float`): The quantity of the item being shipped. +* **weight_unit** (`str`): The unit of measurement for weights. +Fields which are specific to this product; they are not used in any other product. + +### Notify Party Field +The party to be notified of the arrival of the goods. + +A `BillOfLadingV1NotifyParty` implements the following attributes: + +* **address** (`str`): The address of the notify party. +* **email** (`str`): The email of the shipper. +* **name** (`str`): The name of the notify party. +* **phone** (`str`): The phone number of the notify party. +Fields which are specific to this product; they are not used in any other product. + +### Shipper Field +The party responsible for shipping the goods. + +A `BillOfLadingV1Shipper` implements the following attributes: + +* **address** (`str`): The address of the shipper. +* **email** (`str`): The email of the shipper. +* **name** (`str`): The name of the shipper. +* **phone** (`str`): The phone number of the shipper. + +# Attributes +The following fields are extracted for Bill of Lading V1: + +## Bill of Lading Number +**bill_of_lading_number** ([StringField](#stringfield)): A unique identifier assigned to a Bill of Lading document. + +```py +print(result.document.inference.prediction.bill_of_lading_number.value) +``` + +## Carrier +**carrier** ([BillOfLadingV1Carrier](#carrier-field)): The shipping company responsible for transporting the goods. + +```py +print(result.document.inference.prediction.carrier.value) +``` + +## Items +**carrier_items** (List[[BillOfLadingV1CarrierItem](#items-field)]): The goods being shipped. + +```py +for carrier_items_elem in result.document.inference.prediction.carrier_items: + print(carrier_items_elem.value) +``` + +## Consignee +**consignee** ([BillOfLadingV1Consignee](#consignee-field)): The party to whom the goods are being shipped. + +```py +print(result.document.inference.prediction.consignee.value) +``` + +## Date of issue +**date_of_issue** ([DateField](#datefield)): The date when the bill of lading is issued. + +```py +print(result.document.inference.prediction.date_of_issue.value) +``` + +## Departure Date +**departure_date** ([DateField](#datefield)): The date when the vessel departs from the port of loading. + +```py +print(result.document.inference.prediction.departure_date.value) +``` + +## Notify Party +**notify_party** ([BillOfLadingV1NotifyParty](#notify-party-field)): The party to be notified of the arrival of the goods. + +```py +print(result.document.inference.prediction.notify_party.value) +``` + +## Place of Delivery +**place_of_delivery** ([StringField](#stringfield)): The place where the goods are to be delivered. + +```py +print(result.document.inference.prediction.place_of_delivery.value) +``` + +## Port of Discharge +**port_of_discharge** ([StringField](#stringfield)): The port where the goods are unloaded from the vessel. + +```py +print(result.document.inference.prediction.port_of_discharge.value) +``` + +## Port of Loading +**port_of_loading** ([StringField](#stringfield)): The port where the goods are loaded onto the vessel. + +```py +print(result.document.inference.prediction.port_of_loading.value) +``` + +## Shipper +**shipper** ([BillOfLadingV1Shipper](#shipper-field)): The party responsible for shipping the goods. + +```py +print(result.document.inference.prediction.shipper.value) +``` + +# Questions? +[Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g) diff --git a/docs/extras/guide/energy_bill_fra_v1.md b/docs/extras/guide/energy_bill_fra_v1.md new file mode 100644 index 00000000..068b02e9 --- /dev/null +++ b/docs/extras/guide/energy_bill_fra_v1.md @@ -0,0 +1,245 @@ +--- +title: FR Energy Bill OCR Python +category: 622b805aaec68102ea7fcbc2 +slug: python-fr-energy-bill-ocr +parentDoc: 609808f773b0b90051d839de +--- +The Python OCR SDK supports the [Energy Bill API](https://platform.mindee.com/mindee/energy_bill_fra). + +The [sample below](https://github.com/mindee/client-lib-test-data/blob/main/products/energy_bill_fra/default_sample.jpg) can be used for testing purposes. +![Energy Bill sample](https://github.com/mindee/client-lib-test-data/blob/main/products/energy_bill_fra/default_sample.jpg?raw=true) + +# Quick-Start +```py +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.fr.EnergyBillV1, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) + +``` +# Field Types +## Standard Fields +These fields are generic and used in several products. + +### BaseField +Each prediction object contains a set of fields that inherit from the generic `BaseField` class. +A typical `BaseField` object will have the following attributes: + +* **value** (`Union[float, str]`): corresponds to the field value. Can be `None` if no value was extracted. +* **confidence** (`float`): the confidence score of the field prediction. +* **bounding_box** (`[Point, Point, Point, Point]`): contains exactly 4 relative vertices (points) coordinates of a right rectangle containing the field in the document. +* **polygon** (`List[Point]`): contains the relative vertices coordinates (`Point`) of a polygon containing the field in the image. +* **page_id** (`int`): the ID of the page, always `None` when at document-level. +* **reconstructed** (`bool`): indicates whether an object was reconstructed (not extracted as the API gave it). + +> **Note:** A `Point` simply refers to a List of two numbers (`[float, float]`). + + +Aside from the previous attributes, all basic fields have access to a custom `__str__` method that can be used to print their value as a string. + + +### AmountField +The amount field `AmountField` only has one constraint: its **value** is an `Optional[float]`. + +### DateField +Aside from the basic `BaseField` attributes, the date field `DateField` also implements the following: + +* **date_object** (`Date`): an accessible representation of the value as a python object. Can be `None`. + +### StringField +The text field `StringField` only has one constraint: its **value** is an `Optional[str]`. + +## Specific Fields +Fields which are specific to this product; they are not used in any other product. + +### Energy Consumer Field +The entity that consumes the energy. + +A `EnergyBillV1EnergyConsumer` implements the following attributes: + +* **address** (`str`): The address of the energy consumer. +* **name** (`str`): The name of the energy consumer. +Fields which are specific to this product; they are not used in any other product. + +### Energy Supplier Field +The company that supplies the energy. + +A `EnergyBillV1EnergySupplier` implements the following attributes: + +* **address** (`str`): The address of the energy supplier. +* **name** (`str`): The name of the energy supplier. +Fields which are specific to this product; they are not used in any other product. + +### Energy Usage Field +Details of energy consumption. + +A `EnergyBillV1EnergyUsage` implements the following attributes: + +* **description** (`str`): Description or details of the energy usage. +* **end_date** (`str`): The end date of the energy usage. +* **start_date** (`str`): The start date of the energy usage. +* **tax_rate** (`float`): The rate of tax applied to the total cost. +* **total** (`float`): The total cost of energy consumed. +* **unit_price** (`float`): The price per unit of energy consumed. +Fields which are specific to this product; they are not used in any other product. + +### Meter Details Field +Information about the energy meter. + +A `EnergyBillV1MeterDetail` implements the following attributes: + +* **meter_number** (`str`): The unique identifier of the energy meter. +* **meter_type** (`str`): The type of energy meter. + +#### Possible values include: + - electricity + - gas + - water + - None + +* **unit** (`str`): The unit of measurement for energy consumption, which can be kW, m³, or L. +Fields which are specific to this product; they are not used in any other product. + +### Subscription Field +The subscription details fee for the energy service. + +A `EnergyBillV1Subscription` implements the following attributes: + +* **description** (`str`): Description or details of the subscription. +* **end_date** (`str`): The end date of the subscription. +* **start_date** (`str`): The start date of the subscription. +* **tax_rate** (`float`): The rate of tax applied to the total cost. +* **total** (`float`): The total cost of subscription. +* **unit_price** (`float`): The price per unit of subscription. +Fields which are specific to this product; they are not used in any other product. + +### Taxes and Contributions Field +Details of Taxes and Contributions. + +A `EnergyBillV1TaxesAndContribution` implements the following attributes: + +* **description** (`str`): Description or details of the Taxes and Contributions. +* **end_date** (`str`): The end date of the Taxes and Contributions. +* **start_date** (`str`): The start date of the Taxes and Contributions. +* **tax_rate** (`float`): The rate of tax applied to the total cost. +* **total** (`float`): The total cost of Taxes and Contributions. +* **unit_price** (`float`): The price per unit of Taxes and Contributions. + +# Attributes +The following fields are extracted for Energy Bill V1: + +## Contract ID +**contract_id** ([StringField](#stringfield)): The unique identifier associated with a specific contract. + +```py +print(result.document.inference.prediction.contract_id.value) +``` + +## Delivery Point +**delivery_point** ([StringField](#stringfield)): The unique identifier assigned to each electricity or gas consumption point. It specifies the exact location where the energy is delivered. + +```py +print(result.document.inference.prediction.delivery_point.value) +``` + +## Due Date +**due_date** ([DateField](#datefield)): The date by which the payment for the energy invoice is due. + +```py +print(result.document.inference.prediction.due_date.value) +``` + +## Energy Consumer +**energy_consumer** ([EnergyBillV1EnergyConsumer](#energy-consumer-field)): The entity that consumes the energy. + +```py +print(result.document.inference.prediction.energy_consumer.value) +``` + +## Energy Supplier +**energy_supplier** ([EnergyBillV1EnergySupplier](#energy-supplier-field)): The company that supplies the energy. + +```py +print(result.document.inference.prediction.energy_supplier.value) +``` + +## Energy Usage +**energy_usage** (List[[EnergyBillV1EnergyUsage](#energy-usage-field)]): Details of energy consumption. + +```py +for energy_usage_elem in result.document.inference.prediction.energy_usage: + print(energy_usage_elem.value) +``` + +## Invoice Date +**invoice_date** ([DateField](#datefield)): The date when the energy invoice was issued. + +```py +print(result.document.inference.prediction.invoice_date.value) +``` + +## Invoice Number +**invoice_number** ([StringField](#stringfield)): The unique identifier of the energy invoice. + +```py +print(result.document.inference.prediction.invoice_number.value) +``` + +## Meter Details +**meter_details** ([EnergyBillV1MeterDetail](#meter-details-field)): Information about the energy meter. + +```py +print(result.document.inference.prediction.meter_details.value) +``` + +## Subscription +**subscription** (List[[EnergyBillV1Subscription](#subscription-field)]): The subscription details fee for the energy service. + +```py +for subscription_elem in result.document.inference.prediction.subscription: + print(subscription_elem.value) +``` + +## Taxes and Contributions +**taxes_and_contributions** (List[[EnergyBillV1TaxesAndContribution](#taxes-and-contributions-field)]): Details of Taxes and Contributions. + +```py +for taxes_and_contributions_elem in result.document.inference.prediction.taxes_and_contributions: + print(taxes_and_contributions_elem.value) +``` + +## Total Amount +**total_amount** ([AmountField](#amountfield)): The total amount to be paid for the energy invoice. + +```py +print(result.document.inference.prediction.total_amount.value) +``` + +## Total Before Taxes +**total_before_taxes** ([AmountField](#amountfield)): The total amount to be paid for the energy invoice before taxes. + +```py +print(result.document.inference.prediction.total_before_taxes.value) +``` + +## Total Taxes +**total_taxes** ([AmountField](#amountfield)): Total of taxes applied to the invoice. + +```py +print(result.document.inference.prediction.total_taxes.value) +``` + +# Questions? +[Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g) diff --git a/docs/extras/guide/nutrition_facts_v1.md b/docs/extras/guide/nutrition_facts_v1.md new file mode 100644 index 00000000..338ff954 --- /dev/null +++ b/docs/extras/guide/nutrition_facts_v1.md @@ -0,0 +1,293 @@ +--- +title: Nutrition Facts Label OCR Python +category: 622b805aaec68102ea7fcbc2 +slug: python-nutrition-facts-label-ocr +parentDoc: 609808f773b0b90051d839de +--- +The Python OCR SDK supports the [Nutrition Facts Label API](https://platform.mindee.com/mindee/nutrition_facts). + +The [sample below](https://github.com/mindee/client-lib-test-data/blob/main/products/nutrition_facts/default_sample.jpg) can be used for testing purposes. +![Nutrition Facts Label sample](https://github.com/mindee/client-lib-test-data/blob/main/products/nutrition_facts/default_sample.jpg?raw=true) + +# Quick-Start +```py +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.NutritionFactsLabelV1, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) + +``` +# Field Types +## Standard Fields +These fields are generic and used in several products. + +### BaseField +Each prediction object contains a set of fields that inherit from the generic `BaseField` class. +A typical `BaseField` object will have the following attributes: + +* **value** (`Union[float, str]`): corresponds to the field value. Can be `None` if no value was extracted. +* **confidence** (`float`): the confidence score of the field prediction. +* **bounding_box** (`[Point, Point, Point, Point]`): contains exactly 4 relative vertices (points) coordinates of a right rectangle containing the field in the document. +* **polygon** (`List[Point]`): contains the relative vertices coordinates (`Point`) of a polygon containing the field in the image. +* **page_id** (`int`): the ID of the page, always `None` when at document-level. +* **reconstructed** (`bool`): indicates whether an object was reconstructed (not extracted as the API gave it). + +> **Note:** A `Point` simply refers to a List of two numbers (`[float, float]`). + + +Aside from the previous attributes, all basic fields have access to a custom `__str__` method that can be used to print their value as a string. + + +### AmountField +The amount field `AmountField` only has one constraint: its **value** is an `Optional[float]`. + +## Specific Fields +Fields which are specific to this product; they are not used in any other product. + +### Added Sugars Field +The amount of added sugars in the product. + +A `NutritionFactsLabelV1AddedSugar` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of added sugars to consume or not to exceed each day. +* **per_100g** (`float`): The amount of added sugars per 100g of the product. +* **per_serving** (`float`): The amount of added sugars per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Calories Field +The amount of calories in the product. + +A `NutritionFactsLabelV1Calorie` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of calories to consume or not to exceed each day. +* **per_100g** (`float`): The amount of calories per 100g of the product. +* **per_serving** (`float`): The amount of calories per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Cholesterol Field +The amount of cholesterol in the product. + +A `NutritionFactsLabelV1Cholesterol` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of cholesterol to consume or not to exceed each day. +* **per_100g** (`float`): The amount of cholesterol per 100g of the product. +* **per_serving** (`float`): The amount of cholesterol per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Dietary Fiber Field +The amount of dietary fiber in the product. + +A `NutritionFactsLabelV1DietaryFiber` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of dietary fiber to consume or not to exceed each day. +* **per_100g** (`float`): The amount of dietary fiber per 100g of the product. +* **per_serving** (`float`): The amount of dietary fiber per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### nutrients Field +The amount of nutrients in the product. + +A `NutritionFactsLabelV1Nutrient` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of nutrients to consume or not to exceed each day. +* **name** (`str`): The name of nutrients of the product. +* **per_100g** (`float`): The amount of nutrients per 100g of the product. +* **per_serving** (`float`): The amount of nutrients per serving of the product. +* **unit** (`str`): The unit of measurement for the amount of nutrients. +Fields which are specific to this product; they are not used in any other product. + +### Protein Field +The amount of protein in the product. + +A `NutritionFactsLabelV1Protein` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of protein to consume or not to exceed each day. +* **per_100g** (`float`): The amount of protein per 100g of the product. +* **per_serving** (`float`): The amount of protein per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Saturated Fat Field +The amount of saturated fat in the product. + +A `NutritionFactsLabelV1SaturatedFat` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of saturated fat to consume or not to exceed each day. +* **per_100g** (`float`): The amount of saturated fat per 100g of the product. +* **per_serving** (`float`): The amount of saturated fat per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Serving Size Field +The size of a single serving of the product. + +A `NutritionFactsLabelV1ServingSize` implements the following attributes: + +* **amount** (`float`): The amount of a single serving. +* **unit** (`str`): The unit for the amount of a single serving. +Fields which are specific to this product; they are not used in any other product. + +### sodium Field +The amount of sodium in the product. + +A `NutritionFactsLabelV1Sodium` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of sodium to consume or not to exceed each day. +* **per_100g** (`float`): The amount of sodium per 100g of the product. +* **per_serving** (`float`): The amount of sodium per serving of the product. +* **unit** (`str`): The unit of measurement for the amount of sodium. +Fields which are specific to this product; they are not used in any other product. + +### Total Carbohydrate Field +The total amount of carbohydrates in the product. + +A `NutritionFactsLabelV1TotalCarbohydrate` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of total carbohydrates to consume or not to exceed each day. +* **per_100g** (`float`): The amount of total carbohydrates per 100g of the product. +* **per_serving** (`float`): The amount of total carbohydrates per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Total Fat Field +The total amount of fat in the product. + +A `NutritionFactsLabelV1TotalFat` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of total fat to consume or not to exceed each day. +* **per_100g** (`float`): The amount of total fat per 100g of the product. +* **per_serving** (`float`): The amount of total fat per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Total Sugars Field +The total amount of sugars in the product. + +A `NutritionFactsLabelV1TotalSugar` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of total sugars to consume or not to exceed each day. +* **per_100g** (`float`): The amount of total sugars per 100g of the product. +* **per_serving** (`float`): The amount of total sugars per serving of the product. +Fields which are specific to this product; they are not used in any other product. + +### Trans Fat Field +The amount of trans fat in the product. + +A `NutritionFactsLabelV1TransFat` implements the following attributes: + +* **daily_value** (`float`): DVs are the recommended amounts of trans fat to consume or not to exceed each day. +* **per_100g** (`float`): The amount of trans fat per 100g of the product. +* **per_serving** (`float`): The amount of trans fat per serving of the product. + +# Attributes +The following fields are extracted for Nutrition Facts Label V1: + +## Added Sugars +**added_sugars** ([NutritionFactsLabelV1AddedSugar](#added-sugars-field)): The amount of added sugars in the product. + +```py +print(result.document.inference.prediction.added_sugars.value) +``` + +## Calories +**calories** ([NutritionFactsLabelV1Calorie](#calories-field)): The amount of calories in the product. + +```py +print(result.document.inference.prediction.calories.value) +``` + +## Cholesterol +**cholesterol** ([NutritionFactsLabelV1Cholesterol](#cholesterol-field)): The amount of cholesterol in the product. + +```py +print(result.document.inference.prediction.cholesterol.value) +``` + +## Dietary Fiber +**dietary_fiber** ([NutritionFactsLabelV1DietaryFiber](#dietary-fiber-field)): The amount of dietary fiber in the product. + +```py +print(result.document.inference.prediction.dietary_fiber.value) +``` + +## nutrients +**nutrients** (List[[NutritionFactsLabelV1Nutrient](#nutrients-field)]): The amount of nutrients in the product. + +```py +for nutrients_elem in result.document.inference.prediction.nutrients: + print(nutrients_elem.value) +``` + +## Protein +**protein** ([NutritionFactsLabelV1Protein](#protein-field)): The amount of protein in the product. + +```py +print(result.document.inference.prediction.protein.value) +``` + +## Saturated Fat +**saturated_fat** ([NutritionFactsLabelV1SaturatedFat](#saturated-fat-field)): The amount of saturated fat in the product. + +```py +print(result.document.inference.prediction.saturated_fat.value) +``` + +## Serving per Box +**serving_per_box** ([AmountField](#amountfield)): The number of servings in each box of the product. + +```py +print(result.document.inference.prediction.serving_per_box.value) +``` + +## Serving Size +**serving_size** ([NutritionFactsLabelV1ServingSize](#serving-size-field)): The size of a single serving of the product. + +```py +print(result.document.inference.prediction.serving_size.value) +``` + +## sodium +**sodium** ([NutritionFactsLabelV1Sodium](#sodium-field)): The amount of sodium in the product. + +```py +print(result.document.inference.prediction.sodium.value) +``` + +## Total Carbohydrate +**total_carbohydrate** ([NutritionFactsLabelV1TotalCarbohydrate](#total-carbohydrate-field)): The total amount of carbohydrates in the product. + +```py +print(result.document.inference.prediction.total_carbohydrate.value) +``` + +## Total Fat +**total_fat** ([NutritionFactsLabelV1TotalFat](#total-fat-field)): The total amount of fat in the product. + +```py +print(result.document.inference.prediction.total_fat.value) +``` + +## Total Sugars +**total_sugars** ([NutritionFactsLabelV1TotalSugar](#total-sugars-field)): The total amount of sugars in the product. + +```py +print(result.document.inference.prediction.total_sugars.value) +``` + +## Trans Fat +**trans_fat** ([NutritionFactsLabelV1TransFat](#trans-fat-field)): The amount of trans fat in the product. + +```py +print(result.document.inference.prediction.trans_fat.value) +``` + +# Questions? +[Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g) diff --git a/docs/extras/guide/payslip_fra_v2.md b/docs/extras/guide/payslip_fra_v2.md new file mode 100644 index 00000000..956eda55 --- /dev/null +++ b/docs/extras/guide/payslip_fra_v2.md @@ -0,0 +1,216 @@ +--- +title: FR Payslip OCR Python +category: 622b805aaec68102ea7fcbc2 +slug: python-fr-payslip-ocr +parentDoc: 609808f773b0b90051d839de +--- +The Python OCR SDK supports the [Payslip API](https://platform.mindee.com/mindee/payslip_fra). + +The [sample below](https://github.com/mindee/client-lib-test-data/blob/main/products/payslip_fra/default_sample.jpg) can be used for testing purposes. +![Payslip sample](https://github.com/mindee/client-lib-test-data/blob/main/products/payslip_fra/default_sample.jpg?raw=true) + +# Quick-Start +```py +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.fr.PayslipV2, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) + +``` +# Field Types +## Standard Fields +These fields are generic and used in several products. + +### BaseField +Each prediction object contains a set of fields that inherit from the generic `BaseField` class. +A typical `BaseField` object will have the following attributes: + +* **value** (`Union[float, str]`): corresponds to the field value. Can be `None` if no value was extracted. +* **confidence** (`float`): the confidence score of the field prediction. +* **bounding_box** (`[Point, Point, Point, Point]`): contains exactly 4 relative vertices (points) coordinates of a right rectangle containing the field in the document. +* **polygon** (`List[Point]`): contains the relative vertices coordinates (`Point`) of a polygon containing the field in the image. +* **page_id** (`int`): the ID of the page, always `None` when at document-level. +* **reconstructed** (`bool`): indicates whether an object was reconstructed (not extracted as the API gave it). + +> **Note:** A `Point` simply refers to a List of two numbers (`[float, float]`). + + +Aside from the previous attributes, all basic fields have access to a custom `__str__` method that can be used to print their value as a string. + +## Specific Fields +Fields which are specific to this product; they are not used in any other product. + +### Bank Account Details Field +Information about the employee's bank account. + +A `PayslipV2BankAccountDetail` implements the following attributes: + +* **bank_name** (`str`): The name of the bank. +* **iban** (`str`): The IBAN of the bank account. +* **swift** (`str`): The SWIFT code of the bank. +Fields which are specific to this product; they are not used in any other product. + +### Employee Field +Information about the employee. + +A `PayslipV2Employee` implements the following attributes: + +* **address** (`str`): The address of the employee. +* **date_of_birth** (`str`): The date of birth of the employee. +* **first_name** (`str`): The first name of the employee. +* **last_name** (`str`): The last name of the employee. +* **phone_number** (`str`): The phone number of the employee. +* **registration_number** (`str`): The registration number of the employee. +* **social_security_number** (`str`): The social security number of the employee. +Fields which are specific to this product; they are not used in any other product. + +### Employer Field +Information about the employer. + +A `PayslipV2Employer` implements the following attributes: + +* **address** (`str`): The address of the employer. +* **company_id** (`str`): The company ID of the employer. +* **company_site** (`str`): The site of the company. +* **naf_code** (`str`): The NAF code of the employer. +* **name** (`str`): The name of the employer. +* **phone_number** (`str`): The phone number of the employer. +* **urssaf_number** (`str`): The URSSAF number of the employer. +Fields which are specific to this product; they are not used in any other product. + +### Employment Field +Information about the employment. + +A `PayslipV2Employment` implements the following attributes: + +* **category** (`str`): The category of the employment. +* **coefficient** (`float`): The coefficient of the employment. +* **collective_agreement** (`str`): The collective agreement of the employment. +* **job_title** (`str`): The job title of the employee. +* **position_level** (`str`): The position level of the employment. +* **start_date** (`str`): The start date of the employment. +Fields which are specific to this product; they are not used in any other product. + +### Pay Detail Field +Detailed information about the pay. + +A `PayslipV2PayDetail` implements the following attributes: + +* **gross_salary** (`float`): The gross salary of the employee. +* **gross_salary_ytd** (`float`): The year-to-date gross salary of the employee. +* **income_tax_rate** (`float`): The income tax rate of the employee. +* **income_tax_withheld** (`float`): The income tax withheld from the employee's pay. +* **net_paid** (`float`): The net paid amount of the employee. +* **net_paid_before_tax** (`float`): The net paid amount before tax of the employee. +* **net_taxable** (`float`): The net taxable amount of the employee. +* **net_taxable_ytd** (`float`): The year-to-date net taxable amount of the employee. +* **total_cost_employer** (`float`): The total cost to the employer. +* **total_taxes_and_deductions** (`float`): The total taxes and deductions of the employee. +Fields which are specific to this product; they are not used in any other product. + +### Pay Period Field +Information about the pay period. + +A `PayslipV2PayPeriod` implements the following attributes: + +* **end_date** (`str`): The end date of the pay period. +* **month** (`str`): The month of the pay period. +* **payment_date** (`str`): The date of payment for the pay period. +* **start_date** (`str`): The start date of the pay period. +* **year** (`str`): The year of the pay period. +Fields which are specific to this product; they are not used in any other product. + +### PTO Field +Information about paid time off. + +A `PayslipV2Pto` implements the following attributes: + +* **accrued_this_period** (`float`): The amount of paid time off accrued in this period. +* **balance_end_of_period** (`float`): The balance of paid time off at the end of the period. +* **used_this_period** (`float`): The amount of paid time off used in this period. +Fields which are specific to this product; they are not used in any other product. + +### Salary Details Field +Detailed information about the earnings. + +A `PayslipV2SalaryDetail` implements the following attributes: + +* **amount** (`float`): The amount of the earnings. +* **base** (`float`): The base value of the earnings. +* **description** (`str`): The description of the earnings. +* **rate** (`float`): The rate of the earnings. + +# Attributes +The following fields are extracted for Payslip V2: + +## Bank Account Details +**bank_account_details** ([PayslipV2BankAccountDetail](#bank-account-details-field)): Information about the employee's bank account. + +```py +print(result.document.inference.prediction.bank_account_details.value) +``` + +## Employee +**employee** ([PayslipV2Employee](#employee-field)): Information about the employee. + +```py +print(result.document.inference.prediction.employee.value) +``` + +## Employer +**employer** ([PayslipV2Employer](#employer-field)): Information about the employer. + +```py +print(result.document.inference.prediction.employer.value) +``` + +## Employment +**employment** ([PayslipV2Employment](#employment-field)): Information about the employment. + +```py +print(result.document.inference.prediction.employment.value) +``` + +## Pay Detail +**pay_detail** ([PayslipV2PayDetail](#pay-detail-field)): Detailed information about the pay. + +```py +print(result.document.inference.prediction.pay_detail.value) +``` + +## Pay Period +**pay_period** ([PayslipV2PayPeriod](#pay-period-field)): Information about the pay period. + +```py +print(result.document.inference.prediction.pay_period.value) +``` + +## PTO +**pto** ([PayslipV2Pto](#pto-field)): Information about paid time off. + +```py +print(result.document.inference.prediction.pto.value) +``` + +## Salary Details +**salary_details** (List[[PayslipV2SalaryDetail](#salary-details-field)]): Detailed information about the earnings. + +```py +for salary_details_elem in result.document.inference.prediction.salary_details: + print(salary_details_elem.value) +``` + +# Questions? +[Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g) diff --git a/docs/extras/guide/us_mail_v2.md b/docs/extras/guide/us_mail_v2.md new file mode 100644 index 00000000..3740209e --- /dev/null +++ b/docs/extras/guide/us_mail_v2.md @@ -0,0 +1,136 @@ +--- +title: US US Mail OCR Python +category: 622b805aaec68102ea7fcbc2 +slug: python-us-us-mail-ocr +parentDoc: 609808f773b0b90051d839de +--- +The Python OCR SDK supports the [US Mail API](https://platform.mindee.com/mindee/us_mail). + +Using the [sample below](https://github.com/mindee/client-lib-test-data/blob/main/products/us_mail/default_sample.jpg), we are going to illustrate how to extract the data that we want using the OCR SDK. +![US Mail sample](https://github.com/mindee/client-lib-test-data/blob/main/products/us_mail/default_sample.jpg?raw=true) + +# Quick-Start +```py +from mindee import Client, product, AsyncPredictResponse + +# Init a new client +mindee_client = Client(api_key="my-api-key") + +# Load a file from disk +input_doc = mindee_client.source_from_path("/path/to/the/file.ext") + +# Load a file from disk and enqueue it. +result: AsyncPredictResponse = mindee_client.enqueue_and_parse( + product.us.UsMailV2, + input_doc, +) + +# Print a brief summary of the parsed data +print(result.document) + +``` + +**Output (RST):** +```rst +:Sender Name: zed +:Sender Address: + :City: Dallas + :Complete Address: 54321 Elm Street, Dallas, Texas ... + :Postal Code: 54321 + :State: TX + :Street: 54321 Elm Street +:Recipient Names: Jane Doe +:Recipient Addresses: + +-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+ + | City | Complete Address | Is Address Change | Postal Code | Private Mailbox Number | State | Street | + +=================+=====================================+===================+=============+========================+=======+===========================+ + | Detroit | 1234 Market Street PMB 4321, Det... | | 12345 | 4321 | MI | 1234 Market Street | + +-----------------+-------------------------------------+-------------------+-------------+------------------------+-------+---------------------------+ +``` + +# Field Types +## Standard Fields +These fields are generic and used in several products. + +### BaseField +Each prediction object contains a set of fields that inherit from the generic `BaseField` class. +A typical `BaseField` object will have the following attributes: + +* **value** (`Union[float, str]`): corresponds to the field value. Can be `None` if no value was extracted. +* **confidence** (`float`): the confidence score of the field prediction. +* **bounding_box** (`[Point, Point, Point, Point]`): contains exactly 4 relative vertices (points) coordinates of a right rectangle containing the field in the document. +* **polygon** (`List[Point]`): contains the relative vertices coordinates (`Point`) of a polygon containing the field in the image. +* **page_id** (`int`): the ID of the page, always `None` when at document-level. +* **reconstructed** (`bool`): indicates whether an object was reconstructed (not extracted as the API gave it). + +> **Note:** A `Point` simply refers to a List of two numbers (`[float, float]`). + + +Aside from the previous attributes, all basic fields have access to a custom `__str__` method that can be used to print their value as a string. + +### StringField +The text field `StringField` only has one constraint: its **value** is an `Optional[str]`. + +## Specific Fields +Fields which are specific to this product; they are not used in any other product. + +### Recipient Addresses Field +The addresses of the recipients. + +A `UsMailV2RecipientAddress` implements the following attributes: + +* **city** (`str`): The city of the recipient's address. +* **complete** (`str`): The complete address of the recipient. +* **is_address_change** (`bool`): Indicates if the recipient's address is a change of address. +* **postal_code** (`str`): The postal code of the recipient's address. +* **private_mailbox_number** (`str`): The private mailbox number of the recipient's address. +* **state** (`str`): Second part of the ISO 3166-2 code, consisting of two letters indicating the US State. +* **street** (`str`): The street of the recipient's address. +Fields which are specific to this product; they are not used in any other product. + +### Sender Address Field +The address of the sender. + +A `UsMailV2SenderAddress` implements the following attributes: + +* **city** (`str`): The city of the sender's address. +* **complete** (`str`): The complete address of the sender. +* **postal_code** (`str`): The postal code of the sender's address. +* **state** (`str`): Second part of the ISO 3166-2 code, consisting of two letters indicating the US State. +* **street** (`str`): The street of the sender's address. + +# Attributes +The following fields are extracted for US Mail V2: + +## Recipient Addresses +**recipient_addresses** (List[[UsMailV2RecipientAddress](#recipient-addresses-field)]): The addresses of the recipients. + +```py +for recipient_addresses_elem in result.document.inference.prediction.recipient_addresses: + print(recipient_addresses_elem.value) +``` + +## Recipient Names +**recipient_names** (List[[StringField](#stringfield)]): The names of the recipients. + +```py +for recipient_names_elem in result.document.inference.prediction.recipient_names: + print(recipient_names_elem.value) +``` + +## Sender Address +**sender_address** ([UsMailV2SenderAddress](#sender-address-field)): The address of the sender. + +```py +print(result.document.inference.prediction.sender_address.value) +``` + +## Sender Name +**sender_name** ([StringField](#stringfield)): The name of the sender. + +```py +print(result.document.inference.prediction.sender_name.value) +``` + +# Questions? +[Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g) diff --git a/docs/product/bill_of_lading_v1.rst b/docs/product/bill_of_lading_v1.rst new file mode 100644 index 00000000..92bd22bb --- /dev/null +++ b/docs/product/bill_of_lading_v1.rst @@ -0,0 +1,35 @@ +Bill of Lading V1 +----------------- + +**Sample Code:** + +.. literalinclude:: /extras/code_samples/bill_of_lading_v1.txt + :language: Python + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1.BillOfLadingV1 + :members: + :inherited-members: + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1_document.BillOfLadingV1Document + :members: + :inherited-members: + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1_shipper.BillOfLadingV1Shipper + :members: + :inherited-members: + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1_consignee.BillOfLadingV1Consignee + :members: + :inherited-members: + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1_notify_party.BillOfLadingV1NotifyParty + :members: + :inherited-members: + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1_carrier.BillOfLadingV1Carrier + :members: + :inherited-members: + +.. autoclass:: mindee.product.bill_of_lading.bill_of_lading_v1_carrier_item.BillOfLadingV1CarrierItem + :members: + :inherited-members: diff --git a/docs/product/fr/energy_bill_v1.rst b/docs/product/fr/energy_bill_v1.rst new file mode 100644 index 00000000..d2c7b3ae --- /dev/null +++ b/docs/product/fr/energy_bill_v1.rst @@ -0,0 +1,39 @@ +Energy Bill V1 +-------------- + +**Sample Code:** + +.. literalinclude:: /extras/code_samples/energy_bill_fra_v1.txt + :language: Python + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1.EnergyBillV1 + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_document.EnergyBillV1Document + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_energy_supplier.EnergyBillV1EnergySupplier + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_energy_consumer.EnergyBillV1EnergyConsumer + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_subscription.EnergyBillV1Subscription + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_energy_usage.EnergyBillV1EnergyUsage + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_taxes_and_contribution.EnergyBillV1TaxesAndContribution + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.energy_bill.energy_bill_v1_meter_detail.EnergyBillV1MeterDetail + :members: + :inherited-members: diff --git a/docs/product/fr/payslip_v2.rst b/docs/product/fr/payslip_v2.rst new file mode 100644 index 00000000..0ba285bc --- /dev/null +++ b/docs/product/fr/payslip_v2.rst @@ -0,0 +1,47 @@ +Payslip V2 +---------- + +**Sample Code:** + +.. literalinclude:: /extras/code_samples/payslip_fra_v2.txt + :language: Python + +.. autoclass:: mindee.product.fr.payslip.payslip_v2.PayslipV2 + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_document.PayslipV2Document + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_employee.PayslipV2Employee + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_employer.PayslipV2Employer + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_bank_account_detail.PayslipV2BankAccountDetail + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_employment.PayslipV2Employment + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_salary_detail.PayslipV2SalaryDetail + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_pay_detail.PayslipV2PayDetail + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_pto.PayslipV2Pto + :members: + :inherited-members: + +.. autoclass:: mindee.product.fr.payslip.payslip_v2_pay_period.PayslipV2PayPeriod + :members: + :inherited-members: diff --git a/docs/product/nutrition_facts_label_v1.rst b/docs/product/nutrition_facts_label_v1.rst new file mode 100644 index 00000000..997b5048 --- /dev/null +++ b/docs/product/nutrition_facts_label_v1.rst @@ -0,0 +1,67 @@ +Nutrition Facts Label V1 +------------------------ + +**Sample Code:** + +.. literalinclude:: /extras/code_samples/nutrition_facts_v1.txt + :language: Python + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1.NutritionFactsLabelV1 + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_document.NutritionFactsLabelV1Document + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_serving_size.NutritionFactsLabelV1ServingSize + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_calorie.NutritionFactsLabelV1Calorie + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_fat.NutritionFactsLabelV1TotalFat + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_saturated_fat.NutritionFactsLabelV1SaturatedFat + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_trans_fat.NutritionFactsLabelV1TransFat + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_cholesterol.NutritionFactsLabelV1Cholesterol + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_carbohydrate.NutritionFactsLabelV1TotalCarbohydrate + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_dietary_fiber.NutritionFactsLabelV1DietaryFiber + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_sugar.NutritionFactsLabelV1TotalSugar + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_added_sugar.NutritionFactsLabelV1AddedSugar + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_protein.NutritionFactsLabelV1Protein + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_sodium.NutritionFactsLabelV1Sodium + :members: + :inherited-members: + +.. autoclass:: mindee.product.nutrition_facts_label.nutrition_facts_label_v1_nutrient.NutritionFactsLabelV1Nutrient + :members: + :inherited-members: diff --git a/docs/product/us/us_mail_v2.rst b/docs/product/us/us_mail_v2.rst new file mode 100644 index 00000000..0812ccf4 --- /dev/null +++ b/docs/product/us/us_mail_v2.rst @@ -0,0 +1,23 @@ +US Mail V2 +---------- + +**Sample Code:** + +.. literalinclude:: /extras/code_samples/us_mail_v2.txt + :language: Python + +.. autoclass:: mindee.product.us.us_mail.us_mail_v2.UsMailV2 + :members: + :inherited-members: + +.. autoclass:: mindee.product.us.us_mail.us_mail_v2_document.UsMailV2Document + :members: + :inherited-members: + +.. autoclass:: mindee.product.us.us_mail.us_mail_v2_sender_address.UsMailV2SenderAddress + :members: + :inherited-members: + +.. autoclass:: mindee.product.us.us_mail.us_mail_v2_recipient_address.UsMailV2RecipientAddress + :members: + :inherited-members: diff --git a/mindee/parsing/common/summary_helper.py b/mindee/parsing/common/summary_helper.py index 3e67d3d6..cdf0f767 100644 --- a/mindee/parsing/common/summary_helper.py +++ b/mindee/parsing/common/summary_helper.py @@ -22,6 +22,9 @@ def format_for_display( """Truncates line-items to the max width of their corresponding column.""" if not out_string or len(out_string) == 0: return "" + out_string = ( + out_string.replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t") + ) if max_col_size is None: return out_string return ( diff --git a/mindee/product/__init__.py b/mindee/product/__init__.py index df611a9a..6c1e61db 100644 --- a/mindee/product/__init__.py +++ b/mindee/product/__init__.py @@ -1,5 +1,14 @@ from mindee.product import eu, fr, us from mindee.product.barcode_reader import BarcodeReaderV1, BarcodeReaderV1Document +from mindee.product.bill_of_lading import ( + BillOfLadingV1, + BillOfLadingV1Carrier, + BillOfLadingV1CarrierItem, + BillOfLadingV1Consignee, + BillOfLadingV1Document, + BillOfLadingV1NotifyParty, + BillOfLadingV1Shipper, +) from mindee.product.cropper import CropperV1, CropperV1Document from mindee.product.custom import CustomV1, CustomV1Document, CustomV1Page from mindee.product.financial_document import ( @@ -24,6 +33,23 @@ MultiReceiptsDetectorV1, MultiReceiptsDetectorV1Document, ) +from mindee.product.nutrition_facts_label import ( + NutritionFactsLabelV1, + NutritionFactsLabelV1AddedSugar, + NutritionFactsLabelV1Calorie, + NutritionFactsLabelV1Cholesterol, + NutritionFactsLabelV1DietaryFiber, + NutritionFactsLabelV1Document, + NutritionFactsLabelV1Nutrient, + NutritionFactsLabelV1Protein, + NutritionFactsLabelV1SaturatedFat, + NutritionFactsLabelV1ServingSize, + NutritionFactsLabelV1Sodium, + NutritionFactsLabelV1TotalCarbohydrate, + NutritionFactsLabelV1TotalFat, + NutritionFactsLabelV1TotalSugar, + NutritionFactsLabelV1TransFat, +) from mindee.product.passport import PassportV1, PassportV1Document from mindee.product.proof_of_address import ProofOfAddressV1, ProofOfAddressV1Document from mindee.product.receipt import ( diff --git a/mindee/product/bill_of_lading/__init__.py b/mindee/product/bill_of_lading/__init__.py new file mode 100644 index 00000000..6f0c5b4e --- /dev/null +++ b/mindee/product/bill_of_lading/__init__.py @@ -0,0 +1,19 @@ +from mindee.product.bill_of_lading.bill_of_lading_v1 import BillOfLadingV1 +from mindee.product.bill_of_lading.bill_of_lading_v1_carrier import ( + BillOfLadingV1Carrier, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_carrier_item import ( + BillOfLadingV1CarrierItem, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_consignee import ( + BillOfLadingV1Consignee, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_document import ( + BillOfLadingV1Document, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_notify_party import ( + BillOfLadingV1NotifyParty, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_shipper import ( + BillOfLadingV1Shipper, +) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1.py b/mindee/product/bill_of_lading/bill_of_lading_v1.py new file mode 100644 index 00000000..e0a3fa63 --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1.py @@ -0,0 +1,37 @@ +from typing import List + +from mindee.parsing.common import Inference, Page, StringDict +from mindee.product.bill_of_lading.bill_of_lading_v1_document import ( + BillOfLadingV1Document, +) + + +class BillOfLadingV1(Inference): + """Bill of Lading API version 1 inference prediction.""" + + prediction: BillOfLadingV1Document + """Document-level prediction.""" + pages: List[Page[BillOfLadingV1Document]] + """Page-level prediction(s).""" + endpoint_name = "bill_of_lading" + """Name of the endpoint.""" + endpoint_version = "1" + """Version of the endpoint.""" + + def __init__(self, raw_prediction: StringDict): + """ + Bill of Lading v1 inference. + + :param raw_prediction: Raw prediction from the HTTP response. + """ + super().__init__(raw_prediction) + + self.prediction = BillOfLadingV1Document(raw_prediction["prediction"]) + self.pages = [] + for page in raw_prediction["pages"]: + try: + page_prediction = page["prediction"] + except KeyError: + continue + if page_prediction: + self.pages.append(Page(BillOfLadingV1Document, page)) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1_carrier.py b/mindee/product/bill_of_lading/bill_of_lading_v1_carrier.py new file mode 100644 index 00000000..dcf4602f --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1_carrier.py @@ -0,0 +1,61 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class BillOfLadingV1Carrier(FieldPositionMixin, FieldConfidenceMixin): + """The shipping company responsible for transporting the goods.""" + + name: Optional[str] + """The name of the carrier.""" + professional_number: Optional[str] + """The professional number of the carrier.""" + scac: Optional[str] + """The Standard Carrier Alpha Code (SCAC) of the carrier.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.name = raw_prediction["name"] + self.professional_number = raw_prediction["professional_number"] + self.scac = raw_prediction["scac"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["name"] = format_for_display(self.name) + out_dict["professional_number"] = format_for_display(self.professional_number) + out_dict["scac"] = format_for_display(self.scac) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Name: {printable['name']}\n" + out_str += f" :Professional Number: {printable['professional_number']}\n" + out_str += f" :SCAC: {printable['scac']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Name: {printable['name']}, \n" + out_str += f"Professional Number: {printable['professional_number']}, \n" + out_str += f"SCAC: {printable['scac']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1_carrier_item.py b/mindee/product/bill_of_lading/bill_of_lading_v1_carrier_item.py new file mode 100644 index 00000000..e7a4e612 --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1_carrier_item.py @@ -0,0 +1,95 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class BillOfLadingV1CarrierItem(FieldPositionMixin, FieldConfidenceMixin): + """The goods being shipped.""" + + description: Optional[str] + """A description of the item.""" + gross_weight: Optional[float] + """The gross weight of the item.""" + measurement: Optional[float] + """The measurement of the item.""" + measurement_unit: Optional[str] + """The unit of measurement for the measurement.""" + quantity: Optional[float] + """The quantity of the item being shipped.""" + weight_unit: Optional[str] + """The unit of measurement for weights.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.description = raw_prediction["description"] + self.gross_weight = to_opt_float(raw_prediction, "gross_weight") + self.measurement = to_opt_float(raw_prediction, "measurement") + self.measurement_unit = raw_prediction["measurement_unit"] + self.quantity = to_opt_float(raw_prediction, "quantity") + self.weight_unit = raw_prediction["weight_unit"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["gross_weight"] = float_to_string(self.gross_weight) + out_dict["measurement"] = float_to_string(self.measurement) + out_dict["measurement_unit"] = format_for_display(self.measurement_unit) + out_dict["quantity"] = float_to_string(self.quantity) + out_dict["weight_unit"] = format_for_display(self.weight_unit) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description, 36) + out_dict["gross_weight"] = float_to_string(self.gross_weight) + out_dict["measurement"] = float_to_string(self.measurement) + out_dict["measurement_unit"] = format_for_display(self.measurement_unit, None) + out_dict["quantity"] = float_to_string(self.quantity) + out_dict["weight_unit"] = format_for_display(self.weight_unit, None) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['description']:<36} | " + out_str += f"{printable['gross_weight']:<12} | " + out_str += f"{printable['measurement']:<11} | " + out_str += f"{printable['measurement_unit']:<16} | " + out_str += f"{printable['quantity']:<8} | " + out_str += f"{printable['weight_unit']:<11} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Description: {printable['description']}, \n" + out_str += f"Gross Weight: {printable['gross_weight']}, \n" + out_str += f"Measurement: {printable['measurement']}, \n" + out_str += f"Measurement Unit: {printable['measurement_unit']}, \n" + out_str += f"Quantity: {printable['quantity']}, \n" + out_str += f"Weight Unit: {printable['weight_unit']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1_consignee.py b/mindee/product/bill_of_lading/bill_of_lading_v1_consignee.py new file mode 100644 index 00000000..d5fe8215 --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1_consignee.py @@ -0,0 +1,67 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class BillOfLadingV1Consignee(FieldPositionMixin, FieldConfidenceMixin): + """The party to whom the goods are being shipped.""" + + address: Optional[str] + """The address of the consignee.""" + email: Optional[str] + """The email of the shipper.""" + name: Optional[str] + """The name of the consignee.""" + phone: Optional[str] + """The phone number of the consignee.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.email = raw_prediction["email"] + self.name = raw_prediction["name"] + self.phone = raw_prediction["phone"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["email"] = format_for_display(self.email) + out_dict["name"] = format_for_display(self.name) + out_dict["phone"] = format_for_display(self.phone) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Email: {printable['email']}\n" + out_str += f" :Name: {printable['name']}\n" + out_str += f" :Phone: {printable['phone']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Email: {printable['email']}, \n" + out_str += f"Name: {printable['name']}, \n" + out_str += f"Phone: {printable['phone']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1_document.py b/mindee/product/bill_of_lading/bill_of_lading_v1_document.py new file mode 100644 index 00000000..07ae03af --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1_document.py @@ -0,0 +1,148 @@ +from typing import List, Optional + +from mindee.parsing.common import Prediction, StringDict, clean_out_string +from mindee.parsing.standard import DateField, StringField +from mindee.product.bill_of_lading.bill_of_lading_v1_carrier import ( + BillOfLadingV1Carrier, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_carrier_item import ( + BillOfLadingV1CarrierItem, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_consignee import ( + BillOfLadingV1Consignee, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_notify_party import ( + BillOfLadingV1NotifyParty, +) +from mindee.product.bill_of_lading.bill_of_lading_v1_shipper import ( + BillOfLadingV1Shipper, +) + + +class BillOfLadingV1Document(Prediction): + """Bill of Lading API version 1.1 document data.""" + + bill_of_lading_number: StringField + """A unique identifier assigned to a Bill of Lading document.""" + carrier: BillOfLadingV1Carrier + """The shipping company responsible for transporting the goods.""" + carrier_items: List[BillOfLadingV1CarrierItem] + """The goods being shipped.""" + consignee: BillOfLadingV1Consignee + """The party to whom the goods are being shipped.""" + date_of_issue: DateField + """The date when the bill of lading is issued.""" + departure_date: DateField + """The date when the vessel departs from the port of loading.""" + notify_party: BillOfLadingV1NotifyParty + """The party to be notified of the arrival of the goods.""" + place_of_delivery: StringField + """The place where the goods are to be delivered.""" + port_of_discharge: StringField + """The port where the goods are unloaded from the vessel.""" + port_of_loading: StringField + """The port where the goods are loaded onto the vessel.""" + shipper: BillOfLadingV1Shipper + """The party responsible for shipping the goods.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + """ + Bill of Lading document. + + :param raw_prediction: Raw prediction from HTTP response + :param page_id: Page number for multi pages pdf input + """ + super().__init__(raw_prediction, page_id) + self.bill_of_lading_number = StringField( + raw_prediction["bill_of_lading_number"], + page_id=page_id, + ) + self.carrier = BillOfLadingV1Carrier( + raw_prediction["carrier"], + page_id=page_id, + ) + self.carrier_items = [ + BillOfLadingV1CarrierItem(prediction, page_id=page_id) + for prediction in raw_prediction["carrier_items"] + ] + self.consignee = BillOfLadingV1Consignee( + raw_prediction["consignee"], + page_id=page_id, + ) + self.date_of_issue = DateField( + raw_prediction["date_of_issue"], + page_id=page_id, + ) + self.departure_date = DateField( + raw_prediction["departure_date"], + page_id=page_id, + ) + self.notify_party = BillOfLadingV1NotifyParty( + raw_prediction["notify_party"], + page_id=page_id, + ) + self.place_of_delivery = StringField( + raw_prediction["place_of_delivery"], + page_id=page_id, + ) + self.port_of_discharge = StringField( + raw_prediction["port_of_discharge"], + page_id=page_id, + ) + self.port_of_loading = StringField( + raw_prediction["port_of_loading"], + page_id=page_id, + ) + self.shipper = BillOfLadingV1Shipper( + raw_prediction["shipper"], + page_id=page_id, + ) + + @staticmethod + def _carrier_items_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 38}" + out_str += f"+{char * 14}" + out_str += f"+{char * 13}" + out_str += f"+{char * 18}" + out_str += f"+{char * 10}" + out_str += f"+{char * 13}" + return out_str + "+" + + def _carrier_items_to_str(self) -> str: + if not self.carrier_items: + return "" + + lines = f"\n{self._carrier_items_separator('-')}\n ".join( + [item.to_table_line() for item in self.carrier_items] + ) + out_str = "" + out_str += f"\n{self._carrier_items_separator('-')}\n " + out_str += " | Description " + out_str += " | Gross Weight" + out_str += " | Measurement" + out_str += " | Measurement Unit" + out_str += " | Quantity" + out_str += " | Weight Unit" + out_str += f" |\n{self._carrier_items_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._carrier_items_separator('-')}" + return out_str + + def __str__(self) -> str: + out_str: str = f":Bill of Lading Number: {self.bill_of_lading_number}\n" + out_str += f":Shipper:\n{self.shipper.to_field_list()}\n" + out_str += f":Consignee:\n{self.consignee.to_field_list()}\n" + out_str += f":Notify Party:\n{self.notify_party.to_field_list()}\n" + out_str += f":Carrier:\n{self.carrier.to_field_list()}\n" + out_str += f":Items: {self._carrier_items_to_str()}\n" + out_str += f":Port of Loading: {self.port_of_loading}\n" + out_str += f":Port of Discharge: {self.port_of_discharge}\n" + out_str += f":Place of Delivery: {self.place_of_delivery}\n" + out_str += f":Date of issue: {self.date_of_issue}\n" + out_str += f":Departure Date: {self.departure_date}\n" + return clean_out_string(out_str) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1_notify_party.py b/mindee/product/bill_of_lading/bill_of_lading_v1_notify_party.py new file mode 100644 index 00000000..64cc30c4 --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1_notify_party.py @@ -0,0 +1,67 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class BillOfLadingV1NotifyParty(FieldPositionMixin, FieldConfidenceMixin): + """The party to be notified of the arrival of the goods.""" + + address: Optional[str] + """The address of the notify party.""" + email: Optional[str] + """The email of the shipper.""" + name: Optional[str] + """The name of the notify party.""" + phone: Optional[str] + """The phone number of the notify party.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.email = raw_prediction["email"] + self.name = raw_prediction["name"] + self.phone = raw_prediction["phone"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["email"] = format_for_display(self.email) + out_dict["name"] = format_for_display(self.name) + out_dict["phone"] = format_for_display(self.phone) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Email: {printable['email']}\n" + out_str += f" :Name: {printable['name']}\n" + out_str += f" :Phone: {printable['phone']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Email: {printable['email']}, \n" + out_str += f"Name: {printable['name']}, \n" + out_str += f"Phone: {printable['phone']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/bill_of_lading/bill_of_lading_v1_shipper.py b/mindee/product/bill_of_lading/bill_of_lading_v1_shipper.py new file mode 100644 index 00000000..2ca23b35 --- /dev/null +++ b/mindee/product/bill_of_lading/bill_of_lading_v1_shipper.py @@ -0,0 +1,67 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class BillOfLadingV1Shipper(FieldPositionMixin, FieldConfidenceMixin): + """The party responsible for shipping the goods.""" + + address: Optional[str] + """The address of the shipper.""" + email: Optional[str] + """The email of the shipper.""" + name: Optional[str] + """The name of the shipper.""" + phone: Optional[str] + """The phone number of the shipper.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.email = raw_prediction["email"] + self.name = raw_prediction["name"] + self.phone = raw_prediction["phone"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["email"] = format_for_display(self.email) + out_dict["name"] = format_for_display(self.name) + out_dict["phone"] = format_for_display(self.phone) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Email: {printable['email']}\n" + out_str += f" :Name: {printable['name']}\n" + out_str += f" :Phone: {printable['phone']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Email: {printable['email']}, \n" + out_str += f"Name: {printable['name']}, \n" + out_str += f"Phone: {printable['phone']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/financial_document/financial_document_v1_line_item.py b/mindee/product/financial_document/financial_document_v1_line_item.py index 9a426df7..57f0cd9b 100644 --- a/mindee/product/financial_document/financial_document_v1_line_item.py +++ b/mindee/product/financial_document/financial_document_v1_line_item.py @@ -59,6 +59,19 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["product_code"] = format_for_display(self.product_code) + out_dict["quantity"] = float_to_string(self.quantity) + out_dict["tax_amount"] = float_to_string(self.tax_amount) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total_amount"] = float_to_string(self.total_amount) + out_dict["unit_measure"] = format_for_display(self.unit_measure) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["description"] = format_for_display(self.description, 36) out_dict["product_code"] = format_for_display(self.product_code, None) out_dict["quantity"] = float_to_string(self.quantity) @@ -71,7 +84,7 @@ def _printable_values(self) -> Dict[str, str]: def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['description']:<36} | " out_str += f"{printable['product_code']:<12} | " out_str += f"{printable['quantity']:<8} | " diff --git a/mindee/product/fr/__init__.py b/mindee/product/fr/__init__.py index d1aa3e88..45f04df9 100644 --- a/mindee/product/fr/__init__.py +++ b/mindee/product/fr/__init__.py @@ -19,12 +19,44 @@ from mindee.product.fr.carte_vitale.carte_vitale_v1_document import ( CarteVitaleV1Document, ) +from mindee.product.fr.energy_bill.energy_bill_v1 import EnergyBillV1 +from mindee.product.fr.energy_bill.energy_bill_v1_document import EnergyBillV1Document +from mindee.product.fr.energy_bill.energy_bill_v1_energy_consumer import ( + EnergyBillV1EnergyConsumer, +) +from mindee.product.fr.energy_bill.energy_bill_v1_energy_supplier import ( + EnergyBillV1EnergySupplier, +) +from mindee.product.fr.energy_bill.energy_bill_v1_energy_usage import ( + EnergyBillV1EnergyUsage, +) +from mindee.product.fr.energy_bill.energy_bill_v1_meter_detail import ( + EnergyBillV1MeterDetail, +) +from mindee.product.fr.energy_bill.energy_bill_v1_subscription import ( + EnergyBillV1Subscription, +) +from mindee.product.fr.energy_bill.energy_bill_v1_taxes_and_contribution import ( + EnergyBillV1TaxesAndContribution, +) from mindee.product.fr.id_card.id_card_v1 import IdCardV1 from mindee.product.fr.id_card.id_card_v1_document import IdCardV1Document from mindee.product.fr.id_card.id_card_v1_page import IdCardV1Page from mindee.product.fr.id_card.id_card_v2 import IdCardV2 from mindee.product.fr.id_card.id_card_v2_document import IdCardV2Document from mindee.product.fr.id_card.id_card_v2_page import IdCardV2Page +from mindee.product.fr.payslip.payslip_v2 import PayslipV2 +from mindee.product.fr.payslip.payslip_v2_bank_account_detail import ( + PayslipV2BankAccountDetail, +) +from mindee.product.fr.payslip.payslip_v2_document import PayslipV2Document +from mindee.product.fr.payslip.payslip_v2_employee import PayslipV2Employee +from mindee.product.fr.payslip.payslip_v2_employer import PayslipV2Employer +from mindee.product.fr.payslip.payslip_v2_employment import PayslipV2Employment +from mindee.product.fr.payslip.payslip_v2_pay_detail import PayslipV2PayDetail +from mindee.product.fr.payslip.payslip_v2_pay_period import PayslipV2PayPeriod +from mindee.product.fr.payslip.payslip_v2_pto import PayslipV2Pto +from mindee.product.fr.payslip.payslip_v2_salary_detail import PayslipV2SalaryDetail from mindee.product.fr.petrol_receipt.petrol_receipt_v1 import PetrolReceiptV1 from mindee.product.fr.petrol_receipt.petrol_receipt_v1_document import ( PetrolReceiptV1Document, diff --git a/mindee/product/fr/bank_account_details/bank_account_details_v2_bban.py b/mindee/product/fr/bank_account_details/bank_account_details_v2_bban.py index 25a8543b..be6e8b3a 100644 --- a/mindee/product/fr/bank_account_details/bank_account_details_v2_bban.py +++ b/mindee/product/fr/bank_account_details/bank_account_details_v2_bban.py @@ -42,10 +42,10 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} - out_dict["bban_bank_code"] = format_for_display(self.bban_bank_code, None) - out_dict["bban_branch_code"] = format_for_display(self.bban_branch_code, None) - out_dict["bban_key"] = format_for_display(self.bban_key, None) - out_dict["bban_number"] = format_for_display(self.bban_number, None) + out_dict["bban_bank_code"] = format_for_display(self.bban_bank_code) + out_dict["bban_branch_code"] = format_for_display(self.bban_branch_code) + out_dict["bban_key"] = format_for_display(self.bban_key) + out_dict["bban_number"] = format_for_display(self.bban_number) return out_dict def to_field_list(self) -> str: diff --git a/mindee/product/fr/energy_bill/__init__.py b/mindee/product/fr/energy_bill/__init__.py new file mode 100644 index 00000000..b41e135e --- /dev/null +++ b/mindee/product/fr/energy_bill/__init__.py @@ -0,0 +1,20 @@ +from mindee.product.fr.energy_bill.energy_bill_v1 import EnergyBillV1 +from mindee.product.fr.energy_bill.energy_bill_v1_document import EnergyBillV1Document +from mindee.product.fr.energy_bill.energy_bill_v1_energy_consumer import ( + EnergyBillV1EnergyConsumer, +) +from mindee.product.fr.energy_bill.energy_bill_v1_energy_supplier import ( + EnergyBillV1EnergySupplier, +) +from mindee.product.fr.energy_bill.energy_bill_v1_energy_usage import ( + EnergyBillV1EnergyUsage, +) +from mindee.product.fr.energy_bill.energy_bill_v1_meter_detail import ( + EnergyBillV1MeterDetail, +) +from mindee.product.fr.energy_bill.energy_bill_v1_subscription import ( + EnergyBillV1Subscription, +) +from mindee.product.fr.energy_bill.energy_bill_v1_taxes_and_contribution import ( + EnergyBillV1TaxesAndContribution, +) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1.py b/mindee/product/fr/energy_bill/energy_bill_v1.py new file mode 100644 index 00000000..8a73ffc8 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1.py @@ -0,0 +1,37 @@ +from typing import List + +from mindee.parsing.common import Inference, Page, StringDict +from mindee.product.fr.energy_bill.energy_bill_v1_document import ( + EnergyBillV1Document, +) + + +class EnergyBillV1(Inference): + """Energy Bill API version 1 inference prediction.""" + + prediction: EnergyBillV1Document + """Document-level prediction.""" + pages: List[Page[EnergyBillV1Document]] + """Page-level prediction(s).""" + endpoint_name = "energy_bill_fra" + """Name of the endpoint.""" + endpoint_version = "1" + """Version of the endpoint.""" + + def __init__(self, raw_prediction: StringDict): + """ + Energy Bill v1 inference. + + :param raw_prediction: Raw prediction from the HTTP response. + """ + super().__init__(raw_prediction) + + self.prediction = EnergyBillV1Document(raw_prediction["prediction"]) + self.pages = [] + for page in raw_prediction["pages"]: + try: + page_prediction = page["prediction"] + except KeyError: + continue + if page_prediction: + self.pages.append(Page(EnergyBillV1Document, page)) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_document.py b/mindee/product/fr/energy_bill/energy_bill_v1_document.py new file mode 100644 index 00000000..1f35fd86 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_document.py @@ -0,0 +1,239 @@ +from typing import List, Optional + +from mindee.parsing.common import Prediction, StringDict, clean_out_string +from mindee.parsing.standard import AmountField, DateField, StringField +from mindee.product.fr.energy_bill.energy_bill_v1_energy_consumer import ( + EnergyBillV1EnergyConsumer, +) +from mindee.product.fr.energy_bill.energy_bill_v1_energy_supplier import ( + EnergyBillV1EnergySupplier, +) +from mindee.product.fr.energy_bill.energy_bill_v1_energy_usage import ( + EnergyBillV1EnergyUsage, +) +from mindee.product.fr.energy_bill.energy_bill_v1_meter_detail import ( + EnergyBillV1MeterDetail, +) +from mindee.product.fr.energy_bill.energy_bill_v1_subscription import ( + EnergyBillV1Subscription, +) +from mindee.product.fr.energy_bill.energy_bill_v1_taxes_and_contribution import ( + EnergyBillV1TaxesAndContribution, +) + + +class EnergyBillV1Document(Prediction): + """Energy Bill API version 1.0 document data.""" + + contract_id: StringField + """The unique identifier associated with a specific contract.""" + delivery_point: StringField + """ + The unique identifier assigned to each electricity or gas consumption point. It specifies the exact + location where the energy is delivered. + """ + due_date: DateField + """The date by which the payment for the energy invoice is due.""" + energy_consumer: EnergyBillV1EnergyConsumer + """The entity that consumes the energy.""" + energy_supplier: EnergyBillV1EnergySupplier + """The company that supplies the energy.""" + energy_usage: List[EnergyBillV1EnergyUsage] + """Details of energy consumption.""" + invoice_date: DateField + """The date when the energy invoice was issued.""" + invoice_number: StringField + """The unique identifier of the energy invoice.""" + meter_details: EnergyBillV1MeterDetail + """Information about the energy meter.""" + subscription: List[EnergyBillV1Subscription] + """The subscription details fee for the energy service.""" + taxes_and_contributions: List[EnergyBillV1TaxesAndContribution] + """Details of Taxes and Contributions.""" + total_amount: AmountField + """The total amount to be paid for the energy invoice.""" + total_before_taxes: AmountField + """The total amount to be paid for the energy invoice before taxes.""" + total_taxes: AmountField + """Total of taxes applied to the invoice.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + """ + Energy Bill document. + + :param raw_prediction: Raw prediction from HTTP response + :param page_id: Page number for multi pages pdf input + """ + super().__init__(raw_prediction, page_id) + self.contract_id = StringField( + raw_prediction["contract_id"], + page_id=page_id, + ) + self.delivery_point = StringField( + raw_prediction["delivery_point"], + page_id=page_id, + ) + self.due_date = DateField( + raw_prediction["due_date"], + page_id=page_id, + ) + self.energy_consumer = EnergyBillV1EnergyConsumer( + raw_prediction["energy_consumer"], + page_id=page_id, + ) + self.energy_supplier = EnergyBillV1EnergySupplier( + raw_prediction["energy_supplier"], + page_id=page_id, + ) + self.energy_usage = [ + EnergyBillV1EnergyUsage(prediction, page_id=page_id) + for prediction in raw_prediction["energy_usage"] + ] + self.invoice_date = DateField( + raw_prediction["invoice_date"], + page_id=page_id, + ) + self.invoice_number = StringField( + raw_prediction["invoice_number"], + page_id=page_id, + ) + self.meter_details = EnergyBillV1MeterDetail( + raw_prediction["meter_details"], + page_id=page_id, + ) + self.subscription = [ + EnergyBillV1Subscription(prediction, page_id=page_id) + for prediction in raw_prediction["subscription"] + ] + self.taxes_and_contributions = [ + EnergyBillV1TaxesAndContribution(prediction, page_id=page_id) + for prediction in raw_prediction["taxes_and_contributions"] + ] + self.total_amount = AmountField( + raw_prediction["total_amount"], + page_id=page_id, + ) + self.total_before_taxes = AmountField( + raw_prediction["total_before_taxes"], + page_id=page_id, + ) + self.total_taxes = AmountField( + raw_prediction["total_taxes"], + page_id=page_id, + ) + + @staticmethod + def _subscription_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 38}" + out_str += f"+{char * 12}" + out_str += f"+{char * 12}" + out_str += f"+{char * 10}" + out_str += f"+{char * 11}" + out_str += f"+{char * 12}" + return out_str + "+" + + def _subscription_to_str(self) -> str: + if not self.subscription: + return "" + + lines = f"\n{self._subscription_separator('-')}\n ".join( + [item.to_table_line() for item in self.subscription] + ) + out_str = "" + out_str += f"\n{self._subscription_separator('-')}\n " + out_str += " | Description " + out_str += " | End Date " + out_str += " | Start Date" + out_str += " | Tax Rate" + out_str += " | Total " + out_str += " | Unit Price" + out_str += f" |\n{self._subscription_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._subscription_separator('-')}" + return out_str + + @staticmethod + def _energy_usage_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 38}" + out_str += f"+{char * 12}" + out_str += f"+{char * 12}" + out_str += f"+{char * 10}" + out_str += f"+{char * 11}" + out_str += f"+{char * 12}" + return out_str + "+" + + def _energy_usage_to_str(self) -> str: + if not self.energy_usage: + return "" + + lines = f"\n{self._energy_usage_separator('-')}\n ".join( + [item.to_table_line() for item in self.energy_usage] + ) + out_str = "" + out_str += f"\n{self._energy_usage_separator('-')}\n " + out_str += " | Description " + out_str += " | End Date " + out_str += " | Start Date" + out_str += " | Tax Rate" + out_str += " | Total " + out_str += " | Unit Price" + out_str += f" |\n{self._energy_usage_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._energy_usage_separator('-')}" + return out_str + + @staticmethod + def _taxes_and_contributions_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 38}" + out_str += f"+{char * 12}" + out_str += f"+{char * 12}" + out_str += f"+{char * 10}" + out_str += f"+{char * 11}" + out_str += f"+{char * 12}" + return out_str + "+" + + def _taxes_and_contributions_to_str(self) -> str: + if not self.taxes_and_contributions: + return "" + + lines = f"\n{self._taxes_and_contributions_separator('-')}\n ".join( + [item.to_table_line() for item in self.taxes_and_contributions] + ) + out_str = "" + out_str += f"\n{self._taxes_and_contributions_separator('-')}\n " + out_str += " | Description " + out_str += " | End Date " + out_str += " | Start Date" + out_str += " | Tax Rate" + out_str += " | Total " + out_str += " | Unit Price" + out_str += f" |\n{self._taxes_and_contributions_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._taxes_and_contributions_separator('-')}" + return out_str + + def __str__(self) -> str: + out_str: str = f":Invoice Number: {self.invoice_number}\n" + out_str += f":Contract ID: {self.contract_id}\n" + out_str += f":Delivery Point: {self.delivery_point}\n" + out_str += f":Invoice Date: {self.invoice_date}\n" + out_str += f":Due Date: {self.due_date}\n" + out_str += f":Total Before Taxes: {self.total_before_taxes}\n" + out_str += f":Total Taxes: {self.total_taxes}\n" + out_str += f":Total Amount: {self.total_amount}\n" + out_str += f":Energy Supplier:\n{self.energy_supplier.to_field_list()}\n" + out_str += f":Energy Consumer:\n{self.energy_consumer.to_field_list()}\n" + out_str += f":Subscription: {self._subscription_to_str()}\n" + out_str += f":Energy Usage: {self._energy_usage_to_str()}\n" + out_str += ( + f":Taxes and Contributions: {self._taxes_and_contributions_to_str()}\n" + ) + out_str += f":Meter Details:\n{self.meter_details.to_field_list()}\n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_energy_consumer.py b/mindee/product/fr/energy_bill/energy_bill_v1_energy_consumer.py new file mode 100644 index 00000000..ceb0d1d3 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_energy_consumer.py @@ -0,0 +1,55 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class EnergyBillV1EnergyConsumer(FieldPositionMixin, FieldConfidenceMixin): + """The entity that consumes the energy.""" + + address: Optional[str] + """The address of the energy consumer.""" + name: Optional[str] + """The name of the energy consumer.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.name = raw_prediction["name"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["name"] = format_for_display(self.name) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Name: {printable['name']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Name: {printable['name']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_energy_supplier.py b/mindee/product/fr/energy_bill/energy_bill_v1_energy_supplier.py new file mode 100644 index 00000000..20053694 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_energy_supplier.py @@ -0,0 +1,55 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class EnergyBillV1EnergySupplier(FieldPositionMixin, FieldConfidenceMixin): + """The company that supplies the energy.""" + + address: Optional[str] + """The address of the energy supplier.""" + name: Optional[str] + """The name of the energy supplier.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.name = raw_prediction["name"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["name"] = format_for_display(self.name) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Name: {printable['name']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Name: {printable['name']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_energy_usage.py b/mindee/product/fr/energy_bill/energy_bill_v1_energy_usage.py new file mode 100644 index 00000000..ba0aa9b7 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_energy_usage.py @@ -0,0 +1,95 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class EnergyBillV1EnergyUsage(FieldPositionMixin, FieldConfidenceMixin): + """Details of energy consumption.""" + + description: Optional[str] + """Description or details of the energy usage.""" + end_date: Optional[str] + """The end date of the energy usage.""" + start_date: Optional[str] + """The start date of the energy usage.""" + tax_rate: Optional[float] + """The rate of tax applied to the total cost.""" + total: Optional[float] + """The total cost of energy consumed.""" + unit_price: Optional[float] + """The price per unit of energy consumed.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.description = raw_prediction["description"] + self.end_date = raw_prediction["end_date"] + self.start_date = raw_prediction["start_date"] + self.tax_rate = to_opt_float(raw_prediction, "tax_rate") + self.total = to_opt_float(raw_prediction, "total") + self.unit_price = to_opt_float(raw_prediction, "unit_price") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["end_date"] = format_for_display(self.end_date) + out_dict["start_date"] = format_for_display(self.start_date) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total"] = float_to_string(self.total) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description, 36) + out_dict["end_date"] = format_for_display(self.end_date, 10) + out_dict["start_date"] = format_for_display(self.start_date, None) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total"] = float_to_string(self.total) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['description']:<36} | " + out_str += f"{printable['end_date']:<10} | " + out_str += f"{printable['start_date']:<10} | " + out_str += f"{printable['tax_rate']:<8} | " + out_str += f"{printable['total']:<9} | " + out_str += f"{printable['unit_price']:<10} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Description: {printable['description']}, \n" + out_str += f"End Date: {printable['end_date']}, \n" + out_str += f"Start Date: {printable['start_date']}, \n" + out_str += f"Tax Rate: {printable['tax_rate']}, \n" + out_str += f"Total: {printable['total']}, \n" + out_str += f"Unit Price: {printable['unit_price']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_meter_detail.py b/mindee/product/fr/energy_bill/energy_bill_v1_meter_detail.py new file mode 100644 index 00000000..33bb9127 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_meter_detail.py @@ -0,0 +1,61 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class EnergyBillV1MeterDetail(FieldPositionMixin, FieldConfidenceMixin): + """Information about the energy meter.""" + + meter_number: Optional[str] + """The unique identifier of the energy meter.""" + meter_type: Optional[str] + """The type of energy meter.""" + unit: Optional[str] + """The unit of measurement for energy consumption, which can be kW, m³, or L.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.meter_number = raw_prediction["meter_number"] + self.meter_type = raw_prediction["meter_type"] + self.unit = raw_prediction["unit"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["meter_number"] = format_for_display(self.meter_number) + out_dict["meter_type"] = format_for_display(self.meter_type) + out_dict["unit"] = format_for_display(self.unit) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Meter Number: {printable['meter_number']}\n" + out_str += f" :Meter Type: {printable['meter_type']}\n" + out_str += f" :Unit of Measure: {printable['unit']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Meter Number: {printable['meter_number']}, \n" + out_str += f"Meter Type: {printable['meter_type']}, \n" + out_str += f"Unit of Measure: {printable['unit']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_subscription.py b/mindee/product/fr/energy_bill/energy_bill_v1_subscription.py new file mode 100644 index 00000000..ce6b87bb --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_subscription.py @@ -0,0 +1,95 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class EnergyBillV1Subscription(FieldPositionMixin, FieldConfidenceMixin): + """The subscription details fee for the energy service.""" + + description: Optional[str] + """Description or details of the subscription.""" + end_date: Optional[str] + """The end date of the subscription.""" + start_date: Optional[str] + """The start date of the subscription.""" + tax_rate: Optional[float] + """The rate of tax applied to the total cost.""" + total: Optional[float] + """The total cost of subscription.""" + unit_price: Optional[float] + """The price per unit of subscription.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.description = raw_prediction["description"] + self.end_date = raw_prediction["end_date"] + self.start_date = raw_prediction["start_date"] + self.tax_rate = to_opt_float(raw_prediction, "tax_rate") + self.total = to_opt_float(raw_prediction, "total") + self.unit_price = to_opt_float(raw_prediction, "unit_price") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["end_date"] = format_for_display(self.end_date) + out_dict["start_date"] = format_for_display(self.start_date) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total"] = float_to_string(self.total) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description, 36) + out_dict["end_date"] = format_for_display(self.end_date, 10) + out_dict["start_date"] = format_for_display(self.start_date, None) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total"] = float_to_string(self.total) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['description']:<36} | " + out_str += f"{printable['end_date']:<10} | " + out_str += f"{printable['start_date']:<10} | " + out_str += f"{printable['tax_rate']:<8} | " + out_str += f"{printable['total']:<9} | " + out_str += f"{printable['unit_price']:<10} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Description: {printable['description']}, \n" + out_str += f"End Date: {printable['end_date']}, \n" + out_str += f"Start Date: {printable['start_date']}, \n" + out_str += f"Tax Rate: {printable['tax_rate']}, \n" + out_str += f"Total: {printable['total']}, \n" + out_str += f"Unit Price: {printable['unit_price']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/energy_bill/energy_bill_v1_taxes_and_contribution.py b/mindee/product/fr/energy_bill/energy_bill_v1_taxes_and_contribution.py new file mode 100644 index 00000000..80a437b6 --- /dev/null +++ b/mindee/product/fr/energy_bill/energy_bill_v1_taxes_and_contribution.py @@ -0,0 +1,95 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class EnergyBillV1TaxesAndContribution(FieldPositionMixin, FieldConfidenceMixin): + """Details of Taxes and Contributions.""" + + description: Optional[str] + """Description or details of the Taxes and Contributions.""" + end_date: Optional[str] + """The end date of the Taxes and Contributions.""" + start_date: Optional[str] + """The start date of the Taxes and Contributions.""" + tax_rate: Optional[float] + """The rate of tax applied to the total cost.""" + total: Optional[float] + """The total cost of Taxes and Contributions.""" + unit_price: Optional[float] + """The price per unit of Taxes and Contributions.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.description = raw_prediction["description"] + self.end_date = raw_prediction["end_date"] + self.start_date = raw_prediction["start_date"] + self.tax_rate = to_opt_float(raw_prediction, "tax_rate") + self.total = to_opt_float(raw_prediction, "total") + self.unit_price = to_opt_float(raw_prediction, "unit_price") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["end_date"] = format_for_display(self.end_date) + out_dict["start_date"] = format_for_display(self.start_date) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total"] = float_to_string(self.total) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description, 36) + out_dict["end_date"] = format_for_display(self.end_date, 10) + out_dict["start_date"] = format_for_display(self.start_date, None) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total"] = float_to_string(self.total) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['description']:<36} | " + out_str += f"{printable['end_date']:<10} | " + out_str += f"{printable['start_date']:<10} | " + out_str += f"{printable['tax_rate']:<8} | " + out_str += f"{printable['total']:<9} | " + out_str += f"{printable['unit_price']:<10} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Description: {printable['description']}, \n" + out_str += f"End Date: {printable['end_date']}, \n" + out_str += f"Start Date: {printable['start_date']}, \n" + out_str += f"Tax Rate: {printable['tax_rate']}, \n" + out_str += f"Total: {printable['total']}, \n" + out_str += f"Unit Price: {printable['unit_price']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/__init__.py b/mindee/product/fr/payslip/__init__.py new file mode 100644 index 00000000..81cde194 --- /dev/null +++ b/mindee/product/fr/payslip/__init__.py @@ -0,0 +1,12 @@ +from mindee.product.fr.payslip.payslip_v2 import PayslipV2 +from mindee.product.fr.payslip.payslip_v2_bank_account_detail import ( + PayslipV2BankAccountDetail, +) +from mindee.product.fr.payslip.payslip_v2_document import PayslipV2Document +from mindee.product.fr.payslip.payslip_v2_employee import PayslipV2Employee +from mindee.product.fr.payslip.payslip_v2_employer import PayslipV2Employer +from mindee.product.fr.payslip.payslip_v2_employment import PayslipV2Employment +from mindee.product.fr.payslip.payslip_v2_pay_detail import PayslipV2PayDetail +from mindee.product.fr.payslip.payslip_v2_pay_period import PayslipV2PayPeriod +from mindee.product.fr.payslip.payslip_v2_pto import PayslipV2Pto +from mindee.product.fr.payslip.payslip_v2_salary_detail import PayslipV2SalaryDetail diff --git a/mindee/product/fr/payslip/payslip_v2.py b/mindee/product/fr/payslip/payslip_v2.py new file mode 100644 index 00000000..f6a079e5 --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2.py @@ -0,0 +1,37 @@ +from typing import List + +from mindee.parsing.common import Inference, Page, StringDict +from mindee.product.fr.payslip.payslip_v2_document import ( + PayslipV2Document, +) + + +class PayslipV2(Inference): + """Payslip API version 2 inference prediction.""" + + prediction: PayslipV2Document + """Document-level prediction.""" + pages: List[Page[PayslipV2Document]] + """Page-level prediction(s).""" + endpoint_name = "payslip_fra" + """Name of the endpoint.""" + endpoint_version = "2" + """Version of the endpoint.""" + + def __init__(self, raw_prediction: StringDict): + """ + Payslip v2 inference. + + :param raw_prediction: Raw prediction from the HTTP response. + """ + super().__init__(raw_prediction) + + self.prediction = PayslipV2Document(raw_prediction["prediction"]) + self.pages = [] + for page in raw_prediction["pages"]: + try: + page_prediction = page["prediction"] + except KeyError: + continue + if page_prediction: + self.pages.append(Page(PayslipV2Document, page)) diff --git a/mindee/product/fr/payslip/payslip_v2_bank_account_detail.py b/mindee/product/fr/payslip/payslip_v2_bank_account_detail.py new file mode 100644 index 00000000..0e71a0d5 --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_bank_account_detail.py @@ -0,0 +1,61 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class PayslipV2BankAccountDetail(FieldPositionMixin, FieldConfidenceMixin): + """Information about the employee's bank account.""" + + bank_name: Optional[str] + """The name of the bank.""" + iban: Optional[str] + """The IBAN of the bank account.""" + swift: Optional[str] + """The SWIFT code of the bank.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.bank_name = raw_prediction["bank_name"] + self.iban = raw_prediction["iban"] + self.swift = raw_prediction["swift"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["bank_name"] = format_for_display(self.bank_name) + out_dict["iban"] = format_for_display(self.iban) + out_dict["swift"] = format_for_display(self.swift) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Bank Name: {printable['bank_name']}\n" + out_str += f" :IBAN: {printable['iban']}\n" + out_str += f" :SWIFT: {printable['swift']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Bank Name: {printable['bank_name']}, \n" + out_str += f"IBAN: {printable['iban']}, \n" + out_str += f"SWIFT: {printable['swift']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_document.py b/mindee/product/fr/payslip/payslip_v2_document.py new file mode 100644 index 00000000..656a5fcc --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_document.py @@ -0,0 +1,119 @@ +from typing import List, Optional + +from mindee.parsing.common import Prediction, StringDict, clean_out_string +from mindee.product.fr.payslip.payslip_v2_bank_account_detail import ( + PayslipV2BankAccountDetail, +) +from mindee.product.fr.payslip.payslip_v2_employee import PayslipV2Employee +from mindee.product.fr.payslip.payslip_v2_employer import PayslipV2Employer +from mindee.product.fr.payslip.payslip_v2_employment import PayslipV2Employment +from mindee.product.fr.payslip.payslip_v2_pay_detail import PayslipV2PayDetail +from mindee.product.fr.payslip.payslip_v2_pay_period import PayslipV2PayPeriod +from mindee.product.fr.payslip.payslip_v2_pto import PayslipV2Pto +from mindee.product.fr.payslip.payslip_v2_salary_detail import PayslipV2SalaryDetail + + +class PayslipV2Document(Prediction): + """Payslip API version 2.0 document data.""" + + bank_account_details: PayslipV2BankAccountDetail + """Information about the employee's bank account.""" + employee: PayslipV2Employee + """Information about the employee.""" + employer: PayslipV2Employer + """Information about the employer.""" + employment: PayslipV2Employment + """Information about the employment.""" + pay_detail: PayslipV2PayDetail + """Detailed information about the pay.""" + pay_period: PayslipV2PayPeriod + """Information about the pay period.""" + pto: PayslipV2Pto + """Information about paid time off.""" + salary_details: List[PayslipV2SalaryDetail] + """Detailed information about the earnings.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + """ + Payslip document. + + :param raw_prediction: Raw prediction from HTTP response + :param page_id: Page number for multi pages pdf input + """ + super().__init__(raw_prediction, page_id) + self.bank_account_details = PayslipV2BankAccountDetail( + raw_prediction["bank_account_details"], + page_id=page_id, + ) + self.employee = PayslipV2Employee( + raw_prediction["employee"], + page_id=page_id, + ) + self.employer = PayslipV2Employer( + raw_prediction["employer"], + page_id=page_id, + ) + self.employment = PayslipV2Employment( + raw_prediction["employment"], + page_id=page_id, + ) + self.pay_detail = PayslipV2PayDetail( + raw_prediction["pay_detail"], + page_id=page_id, + ) + self.pay_period = PayslipV2PayPeriod( + raw_prediction["pay_period"], + page_id=page_id, + ) + self.pto = PayslipV2Pto( + raw_prediction["pto"], + page_id=page_id, + ) + self.salary_details = [ + PayslipV2SalaryDetail(prediction, page_id=page_id) + for prediction in raw_prediction["salary_details"] + ] + + @staticmethod + def _salary_details_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 14}" + out_str += f"+{char * 11}" + out_str += f"+{char * 38}" + out_str += f"+{char * 11}" + return out_str + "+" + + def _salary_details_to_str(self) -> str: + if not self.salary_details: + return "" + + lines = f"\n{self._salary_details_separator('-')}\n ".join( + [item.to_table_line() for item in self.salary_details] + ) + out_str = "" + out_str += f"\n{self._salary_details_separator('-')}\n " + out_str += " | Amount " + out_str += " | Base " + out_str += " | Description " + out_str += " | Rate " + out_str += f" |\n{self._salary_details_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._salary_details_separator('-')}" + return out_str + + def __str__(self) -> str: + out_str: str = f":Employee:\n{self.employee.to_field_list()}\n" + out_str += f":Employer:\n{self.employer.to_field_list()}\n" + out_str += ( + f":Bank Account Details:\n{self.bank_account_details.to_field_list()}\n" + ) + out_str += f":Employment:\n{self.employment.to_field_list()}\n" + out_str += f":Salary Details: {self._salary_details_to_str()}\n" + out_str += f":Pay Detail:\n{self.pay_detail.to_field_list()}\n" + out_str += f":PTO:\n{self.pto.to_field_list()}\n" + out_str += f":Pay Period:\n{self.pay_period.to_field_list()}\n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_employee.py b/mindee/product/fr/payslip/payslip_v2_employee.py new file mode 100644 index 00000000..be4d393c --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_employee.py @@ -0,0 +1,87 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class PayslipV2Employee(FieldPositionMixin, FieldConfidenceMixin): + """Information about the employee.""" + + address: Optional[str] + """The address of the employee.""" + date_of_birth: Optional[str] + """The date of birth of the employee.""" + first_name: Optional[str] + """The first name of the employee.""" + last_name: Optional[str] + """The last name of the employee.""" + phone_number: Optional[str] + """The phone number of the employee.""" + registration_number: Optional[str] + """The registration number of the employee.""" + social_security_number: Optional[str] + """The social security number of the employee.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.date_of_birth = raw_prediction["date_of_birth"] + self.first_name = raw_prediction["first_name"] + self.last_name = raw_prediction["last_name"] + self.phone_number = raw_prediction["phone_number"] + self.registration_number = raw_prediction["registration_number"] + self.social_security_number = raw_prediction["social_security_number"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["date_of_birth"] = format_for_display(self.date_of_birth) + out_dict["first_name"] = format_for_display(self.first_name) + out_dict["last_name"] = format_for_display(self.last_name) + out_dict["phone_number"] = format_for_display(self.phone_number) + out_dict["registration_number"] = format_for_display(self.registration_number) + out_dict["social_security_number"] = format_for_display( + self.social_security_number + ) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Date of Birth: {printable['date_of_birth']}\n" + out_str += f" :First Name: {printable['first_name']}\n" + out_str += f" :Last Name: {printable['last_name']}\n" + out_str += f" :Phone Number: {printable['phone_number']}\n" + out_str += f" :Registration Number: {printable['registration_number']}\n" + out_str += f" :Social Security Number: {printable['social_security_number']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Date of Birth: {printable['date_of_birth']}, \n" + out_str += f"First Name: {printable['first_name']}, \n" + out_str += f"Last Name: {printable['last_name']}, \n" + out_str += f"Phone Number: {printable['phone_number']}, \n" + out_str += f"Registration Number: {printable['registration_number']}, \n" + out_str += f"Social Security Number: {printable['social_security_number']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_employer.py b/mindee/product/fr/payslip/payslip_v2_employer.py new file mode 100644 index 00000000..fa2a1b76 --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_employer.py @@ -0,0 +1,85 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class PayslipV2Employer(FieldPositionMixin, FieldConfidenceMixin): + """Information about the employer.""" + + address: Optional[str] + """The address of the employer.""" + company_id: Optional[str] + """The company ID of the employer.""" + company_site: Optional[str] + """The site of the company.""" + naf_code: Optional[str] + """The NAF code of the employer.""" + name: Optional[str] + """The name of the employer.""" + phone_number: Optional[str] + """The phone number of the employer.""" + urssaf_number: Optional[str] + """The URSSAF number of the employer.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.address = raw_prediction["address"] + self.company_id = raw_prediction["company_id"] + self.company_site = raw_prediction["company_site"] + self.naf_code = raw_prediction["naf_code"] + self.name = raw_prediction["name"] + self.phone_number = raw_prediction["phone_number"] + self.urssaf_number = raw_prediction["urssaf_number"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["address"] = format_for_display(self.address) + out_dict["company_id"] = format_for_display(self.company_id) + out_dict["company_site"] = format_for_display(self.company_site) + out_dict["naf_code"] = format_for_display(self.naf_code) + out_dict["name"] = format_for_display(self.name) + out_dict["phone_number"] = format_for_display(self.phone_number) + out_dict["urssaf_number"] = format_for_display(self.urssaf_number) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Address: {printable['address']}\n" + out_str += f" :Company ID: {printable['company_id']}\n" + out_str += f" :Company Site: {printable['company_site']}\n" + out_str += f" :NAF Code: {printable['naf_code']}\n" + out_str += f" :Name: {printable['name']}\n" + out_str += f" :Phone Number: {printable['phone_number']}\n" + out_str += f" :URSSAF Number: {printable['urssaf_number']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Address: {printable['address']}, \n" + out_str += f"Company ID: {printable['company_id']}, \n" + out_str += f"Company Site: {printable['company_site']}, \n" + out_str += f"NAF Code: {printable['naf_code']}, \n" + out_str += f"Name: {printable['name']}, \n" + out_str += f"Phone Number: {printable['phone_number']}, \n" + out_str += f"URSSAF Number: {printable['urssaf_number']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_employment.py b/mindee/product/fr/payslip/payslip_v2_employment.py new file mode 100644 index 00000000..d30c3bb0 --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_employment.py @@ -0,0 +1,84 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class PayslipV2Employment(FieldPositionMixin, FieldConfidenceMixin): + """Information about the employment.""" + + category: Optional[str] + """The category of the employment.""" + coefficient: Optional[float] + """The coefficient of the employment.""" + collective_agreement: Optional[str] + """The collective agreement of the employment.""" + job_title: Optional[str] + """The job title of the employee.""" + position_level: Optional[str] + """The position level of the employment.""" + start_date: Optional[str] + """The start date of the employment.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.category = raw_prediction["category"] + self.coefficient = to_opt_float(raw_prediction, "coefficient") + self.collective_agreement = raw_prediction["collective_agreement"] + self.job_title = raw_prediction["job_title"] + self.position_level = raw_prediction["position_level"] + self.start_date = raw_prediction["start_date"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["category"] = format_for_display(self.category) + out_dict["coefficient"] = float_to_string(self.coefficient) + out_dict["collective_agreement"] = format_for_display(self.collective_agreement) + out_dict["job_title"] = format_for_display(self.job_title) + out_dict["position_level"] = format_for_display(self.position_level) + out_dict["start_date"] = format_for_display(self.start_date) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Category: {printable['category']}\n" + out_str += f" :Coefficient: {printable['coefficient']}\n" + out_str += f" :Collective Agreement: {printable['collective_agreement']}\n" + out_str += f" :Job Title: {printable['job_title']}\n" + out_str += f" :Position Level: {printable['position_level']}\n" + out_str += f" :Start Date: {printable['start_date']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Category: {printable['category']}, \n" + out_str += f"Coefficient: {printable['coefficient']}, \n" + out_str += f"Collective Agreement: {printable['collective_agreement']}, \n" + out_str += f"Job Title: {printable['job_title']}, \n" + out_str += f"Position Level: {printable['position_level']}, \n" + out_str += f"Start Date: {printable['start_date']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_pay_detail.py b/mindee/product/fr/payslip/payslip_v2_pay_detail.py new file mode 100644 index 00000000..23a51a93 --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_pay_detail.py @@ -0,0 +1,114 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class PayslipV2PayDetail(FieldPositionMixin, FieldConfidenceMixin): + """Detailed information about the pay.""" + + gross_salary: Optional[float] + """The gross salary of the employee.""" + gross_salary_ytd: Optional[float] + """The year-to-date gross salary of the employee.""" + income_tax_rate: Optional[float] + """The income tax rate of the employee.""" + income_tax_withheld: Optional[float] + """The income tax withheld from the employee's pay.""" + net_paid: Optional[float] + """The net paid amount of the employee.""" + net_paid_before_tax: Optional[float] + """The net paid amount before tax of the employee.""" + net_taxable: Optional[float] + """The net taxable amount of the employee.""" + net_taxable_ytd: Optional[float] + """The year-to-date net taxable amount of the employee.""" + total_cost_employer: Optional[float] + """The total cost to the employer.""" + total_taxes_and_deductions: Optional[float] + """The total taxes and deductions of the employee.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.gross_salary = to_opt_float(raw_prediction, "gross_salary") + self.gross_salary_ytd = to_opt_float(raw_prediction, "gross_salary_ytd") + self.income_tax_rate = to_opt_float(raw_prediction, "income_tax_rate") + self.income_tax_withheld = to_opt_float(raw_prediction, "income_tax_withheld") + self.net_paid = to_opt_float(raw_prediction, "net_paid") + self.net_paid_before_tax = to_opt_float(raw_prediction, "net_paid_before_tax") + self.net_taxable = to_opt_float(raw_prediction, "net_taxable") + self.net_taxable_ytd = to_opt_float(raw_prediction, "net_taxable_ytd") + self.total_cost_employer = to_opt_float(raw_prediction, "total_cost_employer") + self.total_taxes_and_deductions = to_opt_float( + raw_prediction, "total_taxes_and_deductions" + ) + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["gross_salary"] = float_to_string(self.gross_salary) + out_dict["gross_salary_ytd"] = float_to_string(self.gross_salary_ytd) + out_dict["income_tax_rate"] = float_to_string(self.income_tax_rate) + out_dict["income_tax_withheld"] = float_to_string(self.income_tax_withheld) + out_dict["net_paid"] = float_to_string(self.net_paid) + out_dict["net_paid_before_tax"] = float_to_string(self.net_paid_before_tax) + out_dict["net_taxable"] = float_to_string(self.net_taxable) + out_dict["net_taxable_ytd"] = float_to_string(self.net_taxable_ytd) + out_dict["total_cost_employer"] = float_to_string(self.total_cost_employer) + out_dict["total_taxes_and_deductions"] = float_to_string( + self.total_taxes_and_deductions + ) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Gross Salary: {printable['gross_salary']}\n" + out_str += f" :Gross Salary YTD: {printable['gross_salary_ytd']}\n" + out_str += f" :Income Tax Rate: {printable['income_tax_rate']}\n" + out_str += f" :Income Tax Withheld: {printable['income_tax_withheld']}\n" + out_str += f" :Net Paid: {printable['net_paid']}\n" + out_str += f" :Net Paid Before Tax: {printable['net_paid_before_tax']}\n" + out_str += f" :Net Taxable: {printable['net_taxable']}\n" + out_str += f" :Net Taxable YTD: {printable['net_taxable_ytd']}\n" + out_str += f" :Total Cost Employer: {printable['total_cost_employer']}\n" + out_str += f" :Total Taxes and Deductions: {printable['total_taxes_and_deductions']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Gross Salary: {printable['gross_salary']}, \n" + out_str += f"Gross Salary YTD: {printable['gross_salary_ytd']}, \n" + out_str += f"Income Tax Rate: {printable['income_tax_rate']}, \n" + out_str += f"Income Tax Withheld: {printable['income_tax_withheld']}, \n" + out_str += f"Net Paid: {printable['net_paid']}, \n" + out_str += f"Net Paid Before Tax: {printable['net_paid_before_tax']}, \n" + out_str += f"Net Taxable: {printable['net_taxable']}, \n" + out_str += f"Net Taxable YTD: {printable['net_taxable_ytd']}, \n" + out_str += f"Total Cost Employer: {printable['total_cost_employer']}, \n" + out_str += ( + f"Total Taxes and Deductions: {printable['total_taxes_and_deductions']}, \n" + ) + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_pay_period.py b/mindee/product/fr/payslip/payslip_v2_pay_period.py new file mode 100644 index 00000000..c401f8da --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_pay_period.py @@ -0,0 +1,73 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class PayslipV2PayPeriod(FieldPositionMixin, FieldConfidenceMixin): + """Information about the pay period.""" + + end_date: Optional[str] + """The end date of the pay period.""" + month: Optional[str] + """The month of the pay period.""" + payment_date: Optional[str] + """The date of payment for the pay period.""" + start_date: Optional[str] + """The start date of the pay period.""" + year: Optional[str] + """The year of the pay period.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.end_date = raw_prediction["end_date"] + self.month = raw_prediction["month"] + self.payment_date = raw_prediction["payment_date"] + self.start_date = raw_prediction["start_date"] + self.year = raw_prediction["year"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["end_date"] = format_for_display(self.end_date) + out_dict["month"] = format_for_display(self.month) + out_dict["payment_date"] = format_for_display(self.payment_date) + out_dict["start_date"] = format_for_display(self.start_date) + out_dict["year"] = format_for_display(self.year) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :End Date: {printable['end_date']}\n" + out_str += f" :Month: {printable['month']}\n" + out_str += f" :Payment Date: {printable['payment_date']}\n" + out_str += f" :Start Date: {printable['start_date']}\n" + out_str += f" :Year: {printable['year']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"End Date: {printable['end_date']}, \n" + out_str += f"Month: {printable['month']}, \n" + out_str += f"Payment Date: {printable['payment_date']}, \n" + out_str += f"Start Date: {printable['start_date']}, \n" + out_str += f"Year: {printable['year']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_pto.py b/mindee/product/fr/payslip/payslip_v2_pto.py new file mode 100644 index 00000000..9635593d --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_pto.py @@ -0,0 +1,68 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class PayslipV2Pto(FieldPositionMixin, FieldConfidenceMixin): + """Information about paid time off.""" + + accrued_this_period: Optional[float] + """The amount of paid time off accrued in this period.""" + balance_end_of_period: Optional[float] + """The balance of paid time off at the end of the period.""" + used_this_period: Optional[float] + """The amount of paid time off used in this period.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.accrued_this_period = to_opt_float(raw_prediction, "accrued_this_period") + self.balance_end_of_period = to_opt_float( + raw_prediction, "balance_end_of_period" + ) + self.used_this_period = to_opt_float(raw_prediction, "used_this_period") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["accrued_this_period"] = float_to_string(self.accrued_this_period) + out_dict["balance_end_of_period"] = float_to_string(self.balance_end_of_period) + out_dict["used_this_period"] = float_to_string(self.used_this_period) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Accrued This Period: {printable['accrued_this_period']}\n" + out_str += f" :Balance End of Period: {printable['balance_end_of_period']}\n" + out_str += f" :Used This Period: {printable['used_this_period']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Accrued This Period: {printable['accrued_this_period']}, \n" + out_str += f"Balance End of Period: {printable['balance_end_of_period']}, \n" + out_str += f"Used This Period: {printable['used_this_period']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/fr/payslip/payslip_v2_salary_detail.py b/mindee/product/fr/payslip/payslip_v2_salary_detail.py new file mode 100644 index 00000000..0120bb45 --- /dev/null +++ b/mindee/product/fr/payslip/payslip_v2_salary_detail.py @@ -0,0 +1,81 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class PayslipV2SalaryDetail(FieldPositionMixin, FieldConfidenceMixin): + """Detailed information about the earnings.""" + + amount: Optional[float] + """The amount of the earnings.""" + base: Optional[float] + """The base value of the earnings.""" + description: Optional[str] + """The description of the earnings.""" + rate: Optional[float] + """The rate of the earnings.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.amount = to_opt_float(raw_prediction, "amount") + self.base = to_opt_float(raw_prediction, "base") + self.description = raw_prediction["description"] + self.rate = to_opt_float(raw_prediction, "rate") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["amount"] = float_to_string(self.amount) + out_dict["base"] = float_to_string(self.base) + out_dict["description"] = format_for_display(self.description) + out_dict["rate"] = float_to_string(self.rate) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["amount"] = float_to_string(self.amount) + out_dict["base"] = float_to_string(self.base) + out_dict["description"] = format_for_display(self.description, 36) + out_dict["rate"] = float_to_string(self.rate) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['amount']:<12} | " + out_str += f"{printable['base']:<9} | " + out_str += f"{printable['description']:<36} | " + out_str += f"{printable['rate']:<9} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Amount: {printable['amount']}, \n" + out_str += f"Base: {printable['base']}, \n" + out_str += f"Description: {printable['description']}, \n" + out_str += f"Rate: {printable['rate']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/invoice/invoice_v4_line_item.py b/mindee/product/invoice/invoice_v4_line_item.py index f5825f4e..673b382a 100644 --- a/mindee/product/invoice/invoice_v4_line_item.py +++ b/mindee/product/invoice/invoice_v4_line_item.py @@ -59,6 +59,19 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["product_code"] = format_for_display(self.product_code) + out_dict["quantity"] = float_to_string(self.quantity) + out_dict["tax_amount"] = float_to_string(self.tax_amount) + out_dict["tax_rate"] = float_to_string(self.tax_rate) + out_dict["total_amount"] = float_to_string(self.total_amount) + out_dict["unit_measure"] = format_for_display(self.unit_measure) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["description"] = format_for_display(self.description, 36) out_dict["product_code"] = format_for_display(self.product_code, None) out_dict["quantity"] = float_to_string(self.quantity) @@ -71,7 +84,7 @@ def _printable_values(self) -> Dict[str, str]: def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['description']:<36} | " out_str += f"{printable['product_code']:<12} | " out_str += f"{printable['quantity']:<8} | " diff --git a/mindee/product/nutrition_facts_label/__init__.py b/mindee/product/nutrition_facts_label/__init__.py new file mode 100644 index 00000000..fb8d6f0d --- /dev/null +++ b/mindee/product/nutrition_facts_label/__init__.py @@ -0,0 +1,45 @@ +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1 import ( + NutritionFactsLabelV1, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_added_sugar import ( + NutritionFactsLabelV1AddedSugar, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_calorie import ( + NutritionFactsLabelV1Calorie, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_cholesterol import ( + NutritionFactsLabelV1Cholesterol, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_dietary_fiber import ( + NutritionFactsLabelV1DietaryFiber, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_document import ( + NutritionFactsLabelV1Document, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_nutrient import ( + NutritionFactsLabelV1Nutrient, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_protein import ( + NutritionFactsLabelV1Protein, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_saturated_fat import ( + NutritionFactsLabelV1SaturatedFat, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_serving_size import ( + NutritionFactsLabelV1ServingSize, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_sodium import ( + NutritionFactsLabelV1Sodium, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_carbohydrate import ( + NutritionFactsLabelV1TotalCarbohydrate, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_fat import ( + NutritionFactsLabelV1TotalFat, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_sugar import ( + NutritionFactsLabelV1TotalSugar, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_trans_fat import ( + NutritionFactsLabelV1TransFat, +) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1.py new file mode 100644 index 00000000..a6560cd1 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1.py @@ -0,0 +1,37 @@ +from typing import List + +from mindee.parsing.common import Inference, Page, StringDict +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_document import ( + NutritionFactsLabelV1Document, +) + + +class NutritionFactsLabelV1(Inference): + """Nutrition Facts Label API version 1 inference prediction.""" + + prediction: NutritionFactsLabelV1Document + """Document-level prediction.""" + pages: List[Page[NutritionFactsLabelV1Document]] + """Page-level prediction(s).""" + endpoint_name = "nutrition_facts" + """Name of the endpoint.""" + endpoint_version = "1" + """Version of the endpoint.""" + + def __init__(self, raw_prediction: StringDict): + """ + Nutrition Facts Label v1 inference. + + :param raw_prediction: Raw prediction from the HTTP response. + """ + super().__init__(raw_prediction) + + self.prediction = NutritionFactsLabelV1Document(raw_prediction["prediction"]) + self.pages = [] + for page in raw_prediction["pages"]: + try: + page_prediction = page["prediction"] + except KeyError: + continue + if page_prediction: + self.pages.append(Page(NutritionFactsLabelV1Document, page)) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_added_sugar.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_added_sugar.py new file mode 100644 index 00000000..3d01cd09 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_added_sugar.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1AddedSugar(FieldPositionMixin, FieldConfidenceMixin): + """The amount of added sugars in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of added sugars to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of added sugars per 100g of the product.""" + per_serving: Optional[float] + """The amount of added sugars per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_calorie.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_calorie.py new file mode 100644 index 00000000..625cae28 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_calorie.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1Calorie(FieldPositionMixin, FieldConfidenceMixin): + """The amount of calories in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of calories to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of calories per 100g of the product.""" + per_serving: Optional[float] + """The amount of calories per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_cholesterol.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_cholesterol.py new file mode 100644 index 00000000..142712e9 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_cholesterol.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1Cholesterol(FieldPositionMixin, FieldConfidenceMixin): + """The amount of cholesterol in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of cholesterol to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of cholesterol per 100g of the product.""" + per_serving: Optional[float] + """The amount of cholesterol per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_dietary_fiber.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_dietary_fiber.py new file mode 100644 index 00000000..54ccc2b4 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_dietary_fiber.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1DietaryFiber(FieldPositionMixin, FieldConfidenceMixin): + """The amount of dietary fiber in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of dietary fiber to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of dietary fiber per 100g of the product.""" + per_serving: Optional[float] + """The amount of dietary fiber per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_document.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_document.py new file mode 100644 index 00000000..83398900 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_document.py @@ -0,0 +1,191 @@ +from typing import List, Optional + +from mindee.parsing.common import Prediction, StringDict, clean_out_string +from mindee.parsing.standard import AmountField +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_added_sugar import ( + NutritionFactsLabelV1AddedSugar, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_calorie import ( + NutritionFactsLabelV1Calorie, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_cholesterol import ( + NutritionFactsLabelV1Cholesterol, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_dietary_fiber import ( + NutritionFactsLabelV1DietaryFiber, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_nutrient import ( + NutritionFactsLabelV1Nutrient, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_protein import ( + NutritionFactsLabelV1Protein, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_saturated_fat import ( + NutritionFactsLabelV1SaturatedFat, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_serving_size import ( + NutritionFactsLabelV1ServingSize, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_sodium import ( + NutritionFactsLabelV1Sodium, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_carbohydrate import ( + NutritionFactsLabelV1TotalCarbohydrate, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_fat import ( + NutritionFactsLabelV1TotalFat, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_total_sugar import ( + NutritionFactsLabelV1TotalSugar, +) +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_trans_fat import ( + NutritionFactsLabelV1TransFat, +) + + +class NutritionFactsLabelV1Document(Prediction): + """Nutrition Facts Label API version 1.0 document data.""" + + added_sugars: NutritionFactsLabelV1AddedSugar + """The amount of added sugars in the product.""" + calories: NutritionFactsLabelV1Calorie + """The amount of calories in the product.""" + cholesterol: NutritionFactsLabelV1Cholesterol + """The amount of cholesterol in the product.""" + dietary_fiber: NutritionFactsLabelV1DietaryFiber + """The amount of dietary fiber in the product.""" + nutrients: List[NutritionFactsLabelV1Nutrient] + """The amount of nutrients in the product.""" + protein: NutritionFactsLabelV1Protein + """The amount of protein in the product.""" + saturated_fat: NutritionFactsLabelV1SaturatedFat + """The amount of saturated fat in the product.""" + serving_per_box: AmountField + """The number of servings in each box of the product.""" + serving_size: NutritionFactsLabelV1ServingSize + """The size of a single serving of the product.""" + sodium: NutritionFactsLabelV1Sodium + """The amount of sodium in the product.""" + total_carbohydrate: NutritionFactsLabelV1TotalCarbohydrate + """The total amount of carbohydrates in the product.""" + total_fat: NutritionFactsLabelV1TotalFat + """The total amount of fat in the product.""" + total_sugars: NutritionFactsLabelV1TotalSugar + """The total amount of sugars in the product.""" + trans_fat: NutritionFactsLabelV1TransFat + """The amount of trans fat in the product.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + """ + Nutrition Facts Label document. + + :param raw_prediction: Raw prediction from HTTP response + :param page_id: Page number for multi pages pdf input + """ + super().__init__(raw_prediction, page_id) + self.added_sugars = NutritionFactsLabelV1AddedSugar( + raw_prediction["added_sugars"], + page_id=page_id, + ) + self.calories = NutritionFactsLabelV1Calorie( + raw_prediction["calories"], + page_id=page_id, + ) + self.cholesterol = NutritionFactsLabelV1Cholesterol( + raw_prediction["cholesterol"], + page_id=page_id, + ) + self.dietary_fiber = NutritionFactsLabelV1DietaryFiber( + raw_prediction["dietary_fiber"], + page_id=page_id, + ) + self.nutrients = [ + NutritionFactsLabelV1Nutrient(prediction, page_id=page_id) + for prediction in raw_prediction["nutrients"] + ] + self.protein = NutritionFactsLabelV1Protein( + raw_prediction["protein"], + page_id=page_id, + ) + self.saturated_fat = NutritionFactsLabelV1SaturatedFat( + raw_prediction["saturated_fat"], + page_id=page_id, + ) + self.serving_per_box = AmountField( + raw_prediction["serving_per_box"], + page_id=page_id, + ) + self.serving_size = NutritionFactsLabelV1ServingSize( + raw_prediction["serving_size"], + page_id=page_id, + ) + self.sodium = NutritionFactsLabelV1Sodium( + raw_prediction["sodium"], + page_id=page_id, + ) + self.total_carbohydrate = NutritionFactsLabelV1TotalCarbohydrate( + raw_prediction["total_carbohydrate"], + page_id=page_id, + ) + self.total_fat = NutritionFactsLabelV1TotalFat( + raw_prediction["total_fat"], + page_id=page_id, + ) + self.total_sugars = NutritionFactsLabelV1TotalSugar( + raw_prediction["total_sugars"], + page_id=page_id, + ) + self.trans_fat = NutritionFactsLabelV1TransFat( + raw_prediction["trans_fat"], + page_id=page_id, + ) + + @staticmethod + def _nutrients_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 13}" + out_str += f"+{char * 22}" + out_str += f"+{char * 10}" + out_str += f"+{char * 13}" + out_str += f"+{char * 6}" + return out_str + "+" + + def _nutrients_to_str(self) -> str: + if not self.nutrients: + return "" + + lines = f"\n{self._nutrients_separator('-')}\n ".join( + [item.to_table_line() for item in self.nutrients] + ) + out_str = "" + out_str += f"\n{self._nutrients_separator('-')}\n " + out_str += " | Daily Value" + out_str += " | Name " + out_str += " | Per 100g" + out_str += " | Per Serving" + out_str += " | Unit" + out_str += f" |\n{self._nutrients_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._nutrients_separator('-')}" + return out_str + + def __str__(self) -> str: + out_str: str = f":Serving per Box: {self.serving_per_box}\n" + out_str += f":Serving Size:\n{self.serving_size.to_field_list()}\n" + out_str += f":Calories:\n{self.calories.to_field_list()}\n" + out_str += f":Total Fat:\n{self.total_fat.to_field_list()}\n" + out_str += f":Saturated Fat:\n{self.saturated_fat.to_field_list()}\n" + out_str += f":Trans Fat:\n{self.trans_fat.to_field_list()}\n" + out_str += f":Cholesterol:\n{self.cholesterol.to_field_list()}\n" + out_str += f":Total Carbohydrate:\n{self.total_carbohydrate.to_field_list()}\n" + out_str += f":Dietary Fiber:\n{self.dietary_fiber.to_field_list()}\n" + out_str += f":Total Sugars:\n{self.total_sugars.to_field_list()}\n" + out_str += f":Added Sugars:\n{self.added_sugars.to_field_list()}\n" + out_str += f":Protein:\n{self.protein.to_field_list()}\n" + out_str += f":sodium:\n{self.sodium.to_field_list()}\n" + out_str += f":nutrients: {self._nutrients_to_str()}\n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_nutrient.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_nutrient.py new file mode 100644 index 00000000..93fe7a0c --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_nutrient.py @@ -0,0 +1,88 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1Nutrient(FieldPositionMixin, FieldConfidenceMixin): + """The amount of nutrients in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of nutrients to consume or not to exceed each day.""" + name: Optional[str] + """The name of nutrients of the product.""" + per_100g: Optional[float] + """The amount of nutrients per 100g of the product.""" + per_serving: Optional[float] + """The amount of nutrients per serving of the product.""" + unit: Optional[str] + """The unit of measurement for the amount of nutrients.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.name = raw_prediction["name"] + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + self.unit = raw_prediction["unit"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["name"] = format_for_display(self.name) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + out_dict["unit"] = format_for_display(self.unit) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["name"] = format_for_display(self.name, 20) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + out_dict["unit"] = format_for_display(self.unit, None) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['daily_value']:<11} | " + out_str += f"{printable['name']:<20} | " + out_str += f"{printable['per_100g']:<8} | " + out_str += f"{printable['per_serving']:<11} | " + out_str += f"{printable['unit']:<4} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Name: {printable['name']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + out_str += f"Unit: {printable['unit']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_protein.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_protein.py new file mode 100644 index 00000000..1ea78e07 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_protein.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1Protein(FieldPositionMixin, FieldConfidenceMixin): + """The amount of protein in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of protein to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of protein per 100g of the product.""" + per_serving: Optional[float] + """The amount of protein per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_saturated_fat.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_saturated_fat.py new file mode 100644 index 00000000..08fc4cbb --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_saturated_fat.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1SaturatedFat(FieldPositionMixin, FieldConfidenceMixin): + """The amount of saturated fat in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of saturated fat to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of saturated fat per 100g of the product.""" + per_serving: Optional[float] + """The amount of saturated fat per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_serving_size.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_serving_size.py new file mode 100644 index 00000000..6ae24556 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_serving_size.py @@ -0,0 +1,60 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1ServingSize(FieldPositionMixin, FieldConfidenceMixin): + """The size of a single serving of the product.""" + + amount: Optional[float] + """The amount of a single serving.""" + unit: Optional[str] + """The unit for the amount of a single serving.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.amount = to_opt_float(raw_prediction, "amount") + self.unit = raw_prediction["unit"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["amount"] = float_to_string(self.amount) + out_dict["unit"] = format_for_display(self.unit) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Amount: {printable['amount']}\n" + out_str += f" :Unit: {printable['unit']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Amount: {printable['amount']}, \n" + out_str += f"Unit: {printable['unit']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_sodium.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_sodium.py new file mode 100644 index 00000000..ba791a42 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_sodium.py @@ -0,0 +1,72 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1Sodium(FieldPositionMixin, FieldConfidenceMixin): + """The amount of sodium in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of sodium to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of sodium per 100g of the product.""" + per_serving: Optional[float] + """The amount of sodium per serving of the product.""" + unit: Optional[str] + """The unit of measurement for the amount of sodium.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + self.unit = raw_prediction["unit"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + out_dict["unit"] = format_for_display(self.unit) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + out_str += f" :Unit: {printable['unit']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + out_str += f"Unit: {printable['unit']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_carbohydrate.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_carbohydrate.py new file mode 100644 index 00000000..6b1a3e75 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_carbohydrate.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1TotalCarbohydrate(FieldPositionMixin, FieldConfidenceMixin): + """The total amount of carbohydrates in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of total carbohydrates to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of total carbohydrates per 100g of the product.""" + per_serving: Optional[float] + """The amount of total carbohydrates per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_fat.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_fat.py new file mode 100644 index 00000000..81e0103b --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_fat.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1TotalFat(FieldPositionMixin, FieldConfidenceMixin): + """The total amount of fat in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of total fat to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of total fat per 100g of the product.""" + per_serving: Optional[float] + """The amount of total fat per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_sugar.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_sugar.py new file mode 100644 index 00000000..d3406362 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_total_sugar.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1TotalSugar(FieldPositionMixin, FieldConfidenceMixin): + """The total amount of sugars in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of total sugars to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of total sugars per 100g of the product.""" + per_serving: Optional[float] + """The amount of total sugars per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_trans_fat.py b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_trans_fat.py new file mode 100644 index 00000000..4e189007 --- /dev/null +++ b/mindee/product/nutrition_facts_label/nutrition_facts_label_v1_trans_fat.py @@ -0,0 +1,66 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + float_to_string, + to_opt_float, +) + + +class NutritionFactsLabelV1TransFat(FieldPositionMixin, FieldConfidenceMixin): + """The amount of trans fat in the product.""" + + daily_value: Optional[float] + """DVs are the recommended amounts of trans fat to consume or not to exceed each day.""" + per_100g: Optional[float] + """The amount of trans fat per 100g of the product.""" + per_serving: Optional[float] + """The amount of trans fat per serving of the product.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.daily_value = to_opt_float(raw_prediction, "daily_value") + self.per_100g = to_opt_float(raw_prediction, "per_100g") + self.per_serving = to_opt_float(raw_prediction, "per_serving") + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["daily_value"] = float_to_string(self.daily_value) + out_dict["per_100g"] = float_to_string(self.per_100g) + out_dict["per_serving"] = float_to_string(self.per_serving) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :Daily Value: {printable['daily_value']}\n" + out_str += f" :Per 100g: {printable['per_100g']}\n" + out_str += f" :Per Serving: {printable['per_serving']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"Daily Value: {printable['daily_value']}, \n" + out_str += f"Per 100g: {printable['per_100g']}, \n" + out_str += f"Per Serving: {printable['per_serving']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/receipt/receipt_v5_line_item.py b/mindee/product/receipt/receipt_v5_line_item.py index 706fdb70..13723175 100644 --- a/mindee/product/receipt/receipt_v5_line_item.py +++ b/mindee/product/receipt/receipt_v5_line_item.py @@ -47,6 +47,15 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["description"] = format_for_display(self.description) + out_dict["quantity"] = float_to_string(self.quantity) + out_dict["total_amount"] = float_to_string(self.total_amount) + out_dict["unit_price"] = float_to_string(self.unit_price) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["description"] = format_for_display(self.description, 36) out_dict["quantity"] = float_to_string(self.quantity) out_dict["total_amount"] = float_to_string(self.total_amount) @@ -55,7 +64,7 @@ def _printable_values(self) -> Dict[str, str]: def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['description']:<36} | " out_str += f"{printable['quantity']:<8} | " out_str += f"{printable['total_amount']:<12} | " diff --git a/mindee/product/resume/resume_v1_certificate.py b/mindee/product/resume/resume_v1_certificate.py index 4b66d5ee..e5ce1747 100644 --- a/mindee/product/resume/resume_v1_certificate.py +++ b/mindee/product/resume/resume_v1_certificate.py @@ -42,6 +42,15 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["grade"] = format_for_display(self.grade) + out_dict["name"] = format_for_display(self.name) + out_dict["provider"] = format_for_display(self.provider) + out_dict["year"] = format_for_display(self.year) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["grade"] = format_for_display(self.grade, 10) out_dict["name"] = format_for_display(self.name, 30) out_dict["provider"] = format_for_display(self.provider, 25) @@ -50,7 +59,7 @@ def _printable_values(self) -> Dict[str, str]: def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['grade']:<10} | " out_str += f"{printable['name']:<30} | " out_str += f"{printable['provider']:<25} | " diff --git a/mindee/product/resume/resume_v1_education.py b/mindee/product/resume/resume_v1_education.py index ae3723bb..bd2612ae 100644 --- a/mindee/product/resume/resume_v1_education.py +++ b/mindee/product/resume/resume_v1_education.py @@ -51,6 +51,18 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["degree_domain"] = format_for_display(self.degree_domain) + out_dict["degree_type"] = format_for_display(self.degree_type) + out_dict["end_month"] = format_for_display(self.end_month) + out_dict["end_year"] = format_for_display(self.end_year) + out_dict["school"] = format_for_display(self.school) + out_dict["start_month"] = format_for_display(self.start_month) + out_dict["start_year"] = format_for_display(self.start_year) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["degree_domain"] = format_for_display(self.degree_domain, 15) out_dict["degree_type"] = format_for_display(self.degree_type, 25) out_dict["end_month"] = format_for_display(self.end_month, None) @@ -62,7 +74,7 @@ def _printable_values(self) -> Dict[str, str]: def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['degree_domain']:<15} | " out_str += f"{printable['degree_type']:<25} | " out_str += f"{printable['end_month']:<9} | " diff --git a/mindee/product/resume/resume_v1_language.py b/mindee/product/resume/resume_v1_language.py index eec37895..722d8796 100644 --- a/mindee/product/resume/resume_v1_language.py +++ b/mindee/product/resume/resume_v1_language.py @@ -36,13 +36,20 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["language"] = format_for_display(self.language) + out_dict["level"] = format_for_display(self.level) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["language"] = format_for_display(self.language, None) out_dict["level"] = format_for_display(self.level, 20) return out_dict def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['language']:<8} | " out_str += f"{printable['level']:<20} | " return clean_out_string(out_str) diff --git a/mindee/product/resume/resume_v1_professional_experience.py b/mindee/product/resume/resume_v1_professional_experience.py index fa1dc1f3..358c9ecd 100644 --- a/mindee/product/resume/resume_v1_professional_experience.py +++ b/mindee/product/resume/resume_v1_professional_experience.py @@ -54,6 +54,19 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["contract_type"] = format_for_display(self.contract_type) + out_dict["department"] = format_for_display(self.department) + out_dict["employer"] = format_for_display(self.employer) + out_dict["end_month"] = format_for_display(self.end_month) + out_dict["end_year"] = format_for_display(self.end_year) + out_dict["role"] = format_for_display(self.role) + out_dict["start_month"] = format_for_display(self.start_month) + out_dict["start_year"] = format_for_display(self.start_year) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["contract_type"] = format_for_display(self.contract_type, 15) out_dict["department"] = format_for_display(self.department, 10) out_dict["employer"] = format_for_display(self.employer, 25) @@ -66,7 +79,7 @@ def _printable_values(self) -> Dict[str, str]: def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['contract_type']:<15} | " out_str += f"{printable['department']:<10} | " out_str += f"{printable['employer']:<25} | " diff --git a/mindee/product/resume/resume_v1_social_networks_url.py b/mindee/product/resume/resume_v1_social_networks_url.py index daf555ac..4116f220 100644 --- a/mindee/product/resume/resume_v1_social_networks_url.py +++ b/mindee/product/resume/resume_v1_social_networks_url.py @@ -36,13 +36,20 @@ def __init__( def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} + out_dict["name"] = format_for_display(self.name) + out_dict["url"] = format_for_display(self.url) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} out_dict["name"] = format_for_display(self.name, 20) out_dict["url"] = format_for_display(self.url, 50) return out_dict def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['name']:<20} | " out_str += f"{printable['url']:<50} | " return clean_out_string(out_str) diff --git a/mindee/product/us/__init__.py b/mindee/product/us/__init__.py index 8261f82c..8a9012a2 100644 --- a/mindee/product/us/__init__.py +++ b/mindee/product/us/__init__.py @@ -13,6 +13,12 @@ from mindee.product.us.healthcare_card.healthcare_card_v1_document import ( HealthcareCardV1Document, ) +from mindee.product.us.us_mail.us_mail_v2 import UsMailV2 +from mindee.product.us.us_mail.us_mail_v2_document import UsMailV2Document +from mindee.product.us.us_mail.us_mail_v2_recipient_address import ( + UsMailV2RecipientAddress, +) +from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress from mindee.product.us.w9.w9_v1 import W9V1 from mindee.product.us.w9.w9_v1_document import W9V1Document from mindee.product.us.w9.w9_v1_page import W9V1Page diff --git a/mindee/product/us/healthcare_card/healthcare_card_v1_copay.py b/mindee/product/us/healthcare_card/healthcare_card_v1_copay.py index 84f0a793..0e9f4ae7 100644 --- a/mindee/product/us/healthcare_card/healthcare_card_v1_copay.py +++ b/mindee/product/us/healthcare_card/healthcare_card_v1_copay.py @@ -42,12 +42,19 @@ def _printable_values(self) -> Dict[str, str]: """Return values for printing.""" out_dict: Dict[str, str] = {} out_dict["service_fees"] = float_to_string(self.service_fees) + out_dict["service_name"] = format_for_display(self.service_name) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["service_fees"] = float_to_string(self.service_fees) out_dict["service_name"] = format_for_display(self.service_name, None) return out_dict def to_table_line(self) -> str: """Output in a format suitable for inclusion in an rST table.""" - printable = self._printable_values() + printable = self._table_printable_values() out_str: str = f"| {printable['service_fees']:<12} | " out_str += f"{printable['service_name']:<12} | " return clean_out_string(out_str) diff --git a/mindee/product/us/us_mail/__init__.py b/mindee/product/us/us_mail/__init__.py new file mode 100644 index 00000000..3e78f043 --- /dev/null +++ b/mindee/product/us/us_mail/__init__.py @@ -0,0 +1,6 @@ +from mindee.product.us.us_mail.us_mail_v2 import UsMailV2 +from mindee.product.us.us_mail.us_mail_v2_document import UsMailV2Document +from mindee.product.us.us_mail.us_mail_v2_recipient_address import ( + UsMailV2RecipientAddress, +) +from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress diff --git a/mindee/product/us/us_mail/us_mail_v2.py b/mindee/product/us/us_mail/us_mail_v2.py new file mode 100644 index 00000000..6fcc4b7a --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v2.py @@ -0,0 +1,37 @@ +from typing import List + +from mindee.parsing.common import Inference, Page, StringDict +from mindee.product.us.us_mail.us_mail_v2_document import ( + UsMailV2Document, +) + + +class UsMailV2(Inference): + """US Mail API version 2 inference prediction.""" + + prediction: UsMailV2Document + """Document-level prediction.""" + pages: List[Page[UsMailV2Document]] + """Page-level prediction(s).""" + endpoint_name = "us_mail" + """Name of the endpoint.""" + endpoint_version = "2" + """Version of the endpoint.""" + + def __init__(self, raw_prediction: StringDict): + """ + US Mail v2 inference. + + :param raw_prediction: Raw prediction from the HTTP response. + """ + super().__init__(raw_prediction) + + self.prediction = UsMailV2Document(raw_prediction["prediction"]) + self.pages = [] + for page in raw_prediction["pages"]: + try: + page_prediction = page["prediction"] + except KeyError: + continue + if page_prediction: + self.pages.append(Page(UsMailV2Document, page)) diff --git a/mindee/product/us/us_mail/us_mail_v2_document.py b/mindee/product/us/us_mail/us_mail_v2_document.py new file mode 100644 index 00000000..e41c0d2e --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v2_document.py @@ -0,0 +1,93 @@ +from typing import List, Optional + +from mindee.parsing.common import Prediction, StringDict, clean_out_string +from mindee.parsing.standard import StringField +from mindee.product.us.us_mail.us_mail_v2_recipient_address import ( + UsMailV2RecipientAddress, +) +from mindee.product.us.us_mail.us_mail_v2_sender_address import UsMailV2SenderAddress + + +class UsMailV2Document(Prediction): + """US Mail API version 2.0 document data.""" + + recipient_addresses: List[UsMailV2RecipientAddress] + """The addresses of the recipients.""" + recipient_names: List[StringField] + """The names of the recipients.""" + sender_address: UsMailV2SenderAddress + """The address of the sender.""" + sender_name: StringField + """The name of the sender.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + """ + US Mail document. + + :param raw_prediction: Raw prediction from HTTP response + :param page_id: Page number for multi pages pdf input + """ + super().__init__(raw_prediction, page_id) + self.recipient_addresses = [ + UsMailV2RecipientAddress(prediction, page_id=page_id) + for prediction in raw_prediction["recipient_addresses"] + ] + self.recipient_names = [ + StringField(prediction, page_id=page_id) + for prediction in raw_prediction["recipient_names"] + ] + self.sender_address = UsMailV2SenderAddress( + raw_prediction["sender_address"], + page_id=page_id, + ) + self.sender_name = StringField( + raw_prediction["sender_name"], + page_id=page_id, + ) + + @staticmethod + def _recipient_addresses_separator(char: str) -> str: + out_str = " " + out_str += f"+{char * 17}" + out_str += f"+{char * 37}" + out_str += f"+{char * 19}" + out_str += f"+{char * 13}" + out_str += f"+{char * 24}" + out_str += f"+{char * 7}" + out_str += f"+{char * 27}" + return out_str + "+" + + def _recipient_addresses_to_str(self) -> str: + if not self.recipient_addresses: + return "" + + lines = f"\n{self._recipient_addresses_separator('-')}\n ".join( + [item.to_table_line() for item in self.recipient_addresses] + ) + out_str = "" + out_str += f"\n{self._recipient_addresses_separator('-')}\n " + out_str += " | City " + out_str += " | Complete Address " + out_str += " | Is Address Change" + out_str += " | Postal Code" + out_str += " | Private Mailbox Number" + out_str += " | State" + out_str += " | Street " + out_str += f" |\n{self._recipient_addresses_separator('=')}" + out_str += f"\n {lines}" + out_str += f"\n{self._recipient_addresses_separator('-')}" + return out_str + + def __str__(self) -> str: + recipient_names = f"\n { ' ' * 17 }".join( + [str(item) for item in self.recipient_names], + ) + out_str: str = f":Sender Name: {self.sender_name}\n" + out_str += f":Sender Address:\n{self.sender_address.to_field_list()}\n" + out_str += f":Recipient Names: {recipient_names}\n" + out_str += f":Recipient Addresses: {self._recipient_addresses_to_str()}\n" + return clean_out_string(out_str) diff --git a/mindee/product/us/us_mail/us_mail_v2_recipient_address.py b/mindee/product/us/us_mail/us_mail_v2_recipient_address.py new file mode 100644 index 00000000..6a59df10 --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v2_recipient_address.py @@ -0,0 +1,106 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import ( + FieldConfidenceMixin, + FieldPositionMixin, + bool_to_string, + to_opt_bool, +) + + +class UsMailV2RecipientAddress(FieldPositionMixin, FieldConfidenceMixin): + """The addresses of the recipients.""" + + city: Optional[str] + """The city of the recipient's address.""" + complete: Optional[str] + """The complete address of the recipient.""" + is_address_change: Optional[bool] + """Indicates if the recipient's address is a change of address.""" + postal_code: Optional[str] + """The postal code of the recipient's address.""" + private_mailbox_number: Optional[str] + """The private mailbox number of the recipient's address.""" + state: Optional[str] + """Second part of the ISO 3166-2 code, consisting of two letters indicating the US State.""" + street: Optional[str] + """The street of the recipient's address.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.city = raw_prediction["city"] + self.complete = raw_prediction["complete"] + self.is_address_change = to_opt_bool(raw_prediction, "is_address_change") + self.postal_code = raw_prediction["postal_code"] + self.private_mailbox_number = raw_prediction["private_mailbox_number"] + self.state = raw_prediction["state"] + self.street = raw_prediction["street"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["city"] = format_for_display(self.city) + out_dict["complete"] = format_for_display(self.complete) + out_dict["is_address_change"] = bool_to_string(self.is_address_change) + out_dict["postal_code"] = format_for_display(self.postal_code) + out_dict["private_mailbox_number"] = format_for_display( + self.private_mailbox_number + ) + out_dict["state"] = format_for_display(self.state) + out_dict["street"] = format_for_display(self.street) + return out_dict + + def _table_printable_values(self) -> Dict[str, str]: + """Return values for printing inside an RST table.""" + out_dict: Dict[str, str] = {} + out_dict["city"] = format_for_display(self.city, 15) + out_dict["complete"] = format_for_display(self.complete, 35) + out_dict["is_address_change"] = bool_to_string(self.is_address_change) + out_dict["postal_code"] = format_for_display(self.postal_code, None) + out_dict["private_mailbox_number"] = format_for_display( + self.private_mailbox_number, None + ) + out_dict["state"] = format_for_display(self.state, None) + out_dict["street"] = format_for_display(self.street, 25) + return out_dict + + def to_table_line(self) -> str: + """Output in a format suitable for inclusion in an rST table.""" + printable = self._table_printable_values() + out_str: str = f"| {printable['city']:<15} | " + out_str += f"{printable['complete']:<35} | " + out_str += f"{printable['is_address_change']:<17} | " + out_str += f"{printable['postal_code']:<11} | " + out_str += f"{printable['private_mailbox_number']:<22} | " + out_str += f"{printable['state']:<5} | " + out_str += f"{printable['street']:<25} | " + return clean_out_string(out_str) + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"City: {printable['city']}, \n" + out_str += f"Complete Address: {printable['complete']}, \n" + out_str += f"Is Address Change: {printable['is_address_change']}, \n" + out_str += f"Postal Code: {printable['postal_code']}, \n" + out_str += f"Private Mailbox Number: {printable['private_mailbox_number']}, \n" + out_str += f"State: {printable['state']}, \n" + out_str += f"Street: {printable['street']}, \n" + return clean_out_string(out_str) diff --git a/mindee/product/us/us_mail/us_mail_v2_sender_address.py b/mindee/product/us/us_mail/us_mail_v2_sender_address.py new file mode 100644 index 00000000..94857063 --- /dev/null +++ b/mindee/product/us/us_mail/us_mail_v2_sender_address.py @@ -0,0 +1,73 @@ +from typing import Dict, Optional + +from mindee.parsing.common import StringDict, clean_out_string, format_for_display +from mindee.parsing.standard import FieldConfidenceMixin, FieldPositionMixin + + +class UsMailV2SenderAddress(FieldPositionMixin, FieldConfidenceMixin): + """The address of the sender.""" + + city: Optional[str] + """The city of the sender's address.""" + complete: Optional[str] + """The complete address of the sender.""" + postal_code: Optional[str] + """The postal code of the sender's address.""" + state: Optional[str] + """Second part of the ISO 3166-2 code, consisting of two letters indicating the US State.""" + street: Optional[str] + """The street of the sender's address.""" + page_n: int + """The document page on which the information was found.""" + + def __init__( + self, + raw_prediction: StringDict, + page_id: Optional[int] = None, + ): + self._set_confidence(raw_prediction) + self._set_position(raw_prediction) + + if page_id is None: + try: + self.page_n = raw_prediction["page_id"] + except KeyError: + pass + else: + self.page_n = page_id + + self.city = raw_prediction["city"] + self.complete = raw_prediction["complete"] + self.postal_code = raw_prediction["postal_code"] + self.state = raw_prediction["state"] + self.street = raw_prediction["street"] + + def _printable_values(self) -> Dict[str, str]: + """Return values for printing.""" + out_dict: Dict[str, str] = {} + out_dict["city"] = format_for_display(self.city) + out_dict["complete"] = format_for_display(self.complete) + out_dict["postal_code"] = format_for_display(self.postal_code) + out_dict["state"] = format_for_display(self.state) + out_dict["street"] = format_for_display(self.street) + return out_dict + + def to_field_list(self) -> str: + """Output the object in a format suitable for inclusion in an rST field list.""" + printable = self._printable_values() + out_str: str = f" :City: {printable['city']}\n" + out_str += f" :Complete Address: {printable['complete']}\n" + out_str += f" :Postal Code: {printable['postal_code']}\n" + out_str += f" :State: {printable['state']}\n" + out_str += f" :Street: {printable['street']}\n" + return out_str.rstrip() + + def __str__(self) -> str: + """Default string representation.""" + printable = self._printable_values() + out_str: str = f"City: {printable['city']}, \n" + out_str += f"Complete Address: {printable['complete']}, \n" + out_str += f"Postal Code: {printable['postal_code']}, \n" + out_str += f"State: {printable['state']}, \n" + out_str += f"Street: {printable['street']}, \n" + return clean_out_string(out_str) diff --git a/tests/data b/tests/data index 4a55dd2a..f737d62b 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit 4a55dd2a5c3c909d4cd5069a5faface547c20686 +Subproject commit f737d62bb2fb6b064e324f31f25c75767793aa1a diff --git a/tests/product/bill_of_lading/__init__.py b/tests/product/bill_of_lading/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/product/bill_of_lading/test_bill_of_lading_v1.py b/tests/product/bill_of_lading/test_bill_of_lading_v1.py new file mode 100644 index 00000000..0b84d3d1 --- /dev/null +++ b/tests/product/bill_of_lading/test_bill_of_lading_v1.py @@ -0,0 +1,67 @@ +import json + +import pytest + +from mindee.parsing.common.document import Document +from mindee.parsing.common.page import Page +from mindee.product import BillOfLadingV1 +from mindee.product.bill_of_lading.bill_of_lading_v1_document import ( + BillOfLadingV1Document, +) +from tests.product import PRODUCT_DATA_DIR + +RESPONSE_DIR = PRODUCT_DATA_DIR / "bill_of_lading" / "response_v1" + +BillOfLadingV1DocumentType = Document[ + BillOfLadingV1Document, + Page[BillOfLadingV1Document], +] + + +@pytest.fixture +def complete_doc() -> BillOfLadingV1DocumentType: + file_path = RESPONSE_DIR / "complete.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(BillOfLadingV1, json_data["document"]) + + +@pytest.fixture +def empty_doc() -> BillOfLadingV1DocumentType: + file_path = RESPONSE_DIR / "empty.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(BillOfLadingV1, json_data["document"]) + + +def test_complete_doc(complete_doc: BillOfLadingV1DocumentType): + file_path = RESPONSE_DIR / "summary_full.rst" + with open(file_path, "r", encoding="utf-8") as open_file: + reference_str = open_file.read() + assert str(complete_doc) == reference_str + + +def test_empty_doc(empty_doc: BillOfLadingV1DocumentType): + prediction = empty_doc.inference.prediction + assert prediction.bill_of_lading_number.value is None + assert prediction.shipper.address is None + assert prediction.shipper.email is None + assert prediction.shipper.name is None + assert prediction.shipper.phone is None + assert prediction.consignee.address is None + assert prediction.consignee.email is None + assert prediction.consignee.name is None + assert prediction.consignee.phone is None + assert prediction.notify_party.address is None + assert prediction.notify_party.email is None + assert prediction.notify_party.name is None + assert prediction.notify_party.phone is None + assert prediction.carrier.name is None + assert prediction.carrier.professional_number is None + assert prediction.carrier.scac is None + assert len(prediction.carrier_items) == 0 + assert prediction.port_of_loading.value is None + assert prediction.port_of_discharge.value is None + assert prediction.place_of_delivery.value is None + assert prediction.date_of_issue.value is None + assert prediction.departure_date.value is None diff --git a/tests/product/fr/energy_bill/__init__.py b/tests/product/fr/energy_bill/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/product/fr/energy_bill/test_energy_bill_v1.py b/tests/product/fr/energy_bill/test_energy_bill_v1.py new file mode 100644 index 00000000..19db6b4f --- /dev/null +++ b/tests/product/fr/energy_bill/test_energy_bill_v1.py @@ -0,0 +1,63 @@ +import json + +import pytest + +from mindee.parsing.common.document import Document +from mindee.parsing.common.page import Page +from mindee.product.fr import EnergyBillV1 +from mindee.product.fr.energy_bill.energy_bill_v1_document import ( + EnergyBillV1Document, +) +from tests.product import PRODUCT_DATA_DIR + +RESPONSE_DIR = PRODUCT_DATA_DIR / "energy_bill_fra" / "response_v1" + +EnergyBillV1DocumentType = Document[ + EnergyBillV1Document, + Page[EnergyBillV1Document], +] + + +@pytest.fixture +def complete_doc() -> EnergyBillV1DocumentType: + file_path = RESPONSE_DIR / "complete.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(EnergyBillV1, json_data["document"]) + + +@pytest.fixture +def empty_doc() -> EnergyBillV1DocumentType: + file_path = RESPONSE_DIR / "empty.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(EnergyBillV1, json_data["document"]) + + +def test_complete_doc(complete_doc: EnergyBillV1DocumentType): + file_path = RESPONSE_DIR / "summary_full.rst" + with open(file_path, "r", encoding="utf-8") as open_file: + reference_str = open_file.read() + assert str(complete_doc) == reference_str + + +def test_empty_doc(empty_doc: EnergyBillV1DocumentType): + prediction = empty_doc.inference.prediction + assert prediction.invoice_number.value is None + assert prediction.contract_id.value is None + assert prediction.delivery_point.value is None + assert prediction.invoice_date.value is None + assert prediction.due_date.value is None + assert prediction.total_before_taxes.value is None + assert prediction.total_taxes.value is None + assert prediction.total_amount.value is None + assert prediction.energy_supplier.address is None + assert prediction.energy_supplier.name is None + assert prediction.energy_consumer.address is None + assert prediction.energy_consumer.name is None + assert len(prediction.subscription) == 0 + assert len(prediction.energy_usage) == 0 + assert len(prediction.taxes_and_contributions) == 0 + assert prediction.meter_details.meter_number is None + assert prediction.meter_details.meter_type is None + assert prediction.meter_details.unit is None diff --git a/tests/product/fr/payslip/__init__.py b/tests/product/fr/payslip/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/product/fr/payslip/test_payslip_v2.py b/tests/product/fr/payslip/test_payslip_v2.py new file mode 100644 index 00000000..10e9c152 --- /dev/null +++ b/tests/product/fr/payslip/test_payslip_v2.py @@ -0,0 +1,87 @@ +import json + +import pytest + +from mindee.parsing.common.document import Document +from mindee.parsing.common.page import Page +from mindee.product.fr import PayslipV2 +from mindee.product.fr.payslip.payslip_v2_document import ( + PayslipV2Document, +) +from tests.product import PRODUCT_DATA_DIR + +RESPONSE_DIR = PRODUCT_DATA_DIR / "payslip_fra" / "response_v2" + +PayslipV2DocumentType = Document[ + PayslipV2Document, + Page[PayslipV2Document], +] + + +@pytest.fixture +def complete_doc() -> PayslipV2DocumentType: + file_path = RESPONSE_DIR / "complete.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(PayslipV2, json_data["document"]) + + +@pytest.fixture +def empty_doc() -> PayslipV2DocumentType: + file_path = RESPONSE_DIR / "empty.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(PayslipV2, json_data["document"]) + + +def test_complete_doc(complete_doc: PayslipV2DocumentType): + file_path = RESPONSE_DIR / "summary_full.rst" + with open(file_path, "r", encoding="utf-8") as open_file: + reference_str = open_file.read() + assert str(complete_doc) == reference_str + + +def test_empty_doc(empty_doc: PayslipV2DocumentType): + prediction = empty_doc.inference.prediction + assert prediction.employee.address is None + assert prediction.employee.date_of_birth is None + assert prediction.employee.first_name is None + assert prediction.employee.last_name is None + assert prediction.employee.phone_number is None + assert prediction.employee.registration_number is None + assert prediction.employee.social_security_number is None + assert prediction.employer.address is None + assert prediction.employer.company_id is None + assert prediction.employer.company_site is None + assert prediction.employer.naf_code is None + assert prediction.employer.name is None + assert prediction.employer.phone_number is None + assert prediction.employer.urssaf_number is None + assert prediction.bank_account_details.bank_name is None + assert prediction.bank_account_details.iban is None + assert prediction.bank_account_details.swift is None + assert prediction.employment.category is None + assert prediction.employment.coefficient is None + assert prediction.employment.collective_agreement is None + assert prediction.employment.job_title is None + assert prediction.employment.position_level is None + assert prediction.employment.start_date is None + assert len(prediction.salary_details) == 0 + assert prediction.pay_detail.gross_salary is None + assert prediction.pay_detail.gross_salary_ytd is None + assert prediction.pay_detail.income_tax_rate is None + assert prediction.pay_detail.income_tax_withheld is None + assert prediction.pay_detail.net_paid is None + assert prediction.pay_detail.net_paid_before_tax is None + assert prediction.pay_detail.net_taxable is None + assert prediction.pay_detail.net_taxable_ytd is None + assert prediction.pay_detail.total_cost_employer is None + assert prediction.pay_detail.total_taxes_and_deductions is None + assert prediction.pto.accrued_this_period is None + assert prediction.pto.balance_end_of_period is None + assert prediction.pto.used_this_period is None + assert prediction.pay_period.end_date is None + assert prediction.pay_period.month is None + assert prediction.pay_period.payment_date is None + assert prediction.pay_period.start_date is None + assert prediction.pay_period.year is None diff --git a/tests/product/nutrition_facts_label/__init__.py b/tests/product/nutrition_facts_label/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/product/nutrition_facts_label/test_nutrition_facts_label_v1.py b/tests/product/nutrition_facts_label/test_nutrition_facts_label_v1.py new file mode 100644 index 00000000..8a1ee39c --- /dev/null +++ b/tests/product/nutrition_facts_label/test_nutrition_facts_label_v1.py @@ -0,0 +1,83 @@ +import json + +import pytest + +from mindee.parsing.common.document import Document +from mindee.parsing.common.page import Page +from mindee.product import NutritionFactsLabelV1 +from mindee.product.nutrition_facts_label.nutrition_facts_label_v1_document import ( + NutritionFactsLabelV1Document, +) +from tests.product import PRODUCT_DATA_DIR + +RESPONSE_DIR = PRODUCT_DATA_DIR / "nutrition_facts" / "response_v1" + +NutritionFactsLabelV1DocumentType = Document[ + NutritionFactsLabelV1Document, + Page[NutritionFactsLabelV1Document], +] + + +@pytest.fixture +def complete_doc() -> NutritionFactsLabelV1DocumentType: + file_path = RESPONSE_DIR / "complete.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(NutritionFactsLabelV1, json_data["document"]) + + +@pytest.fixture +def empty_doc() -> NutritionFactsLabelV1DocumentType: + file_path = RESPONSE_DIR / "empty.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(NutritionFactsLabelV1, json_data["document"]) + + +def test_complete_doc(complete_doc: NutritionFactsLabelV1DocumentType): + file_path = RESPONSE_DIR / "summary_full.rst" + with open(file_path, "r", encoding="utf-8") as open_file: + reference_str = open_file.read() + assert str(complete_doc) == reference_str + + +def test_empty_doc(empty_doc: NutritionFactsLabelV1DocumentType): + prediction = empty_doc.inference.prediction + assert prediction.serving_per_box.value is None + assert prediction.serving_size.amount is None + assert prediction.serving_size.unit is None + assert prediction.calories.daily_value is None + assert prediction.calories.per_100g is None + assert prediction.calories.per_serving is None + assert prediction.total_fat.daily_value is None + assert prediction.total_fat.per_100g is None + assert prediction.total_fat.per_serving is None + assert prediction.saturated_fat.daily_value is None + assert prediction.saturated_fat.per_100g is None + assert prediction.saturated_fat.per_serving is None + assert prediction.trans_fat.daily_value is None + assert prediction.trans_fat.per_100g is None + assert prediction.trans_fat.per_serving is None + assert prediction.cholesterol.daily_value is None + assert prediction.cholesterol.per_100g is None + assert prediction.cholesterol.per_serving is None + assert prediction.total_carbohydrate.daily_value is None + assert prediction.total_carbohydrate.per_100g is None + assert prediction.total_carbohydrate.per_serving is None + assert prediction.dietary_fiber.daily_value is None + assert prediction.dietary_fiber.per_100g is None + assert prediction.dietary_fiber.per_serving is None + assert prediction.total_sugars.daily_value is None + assert prediction.total_sugars.per_100g is None + assert prediction.total_sugars.per_serving is None + assert prediction.added_sugars.daily_value is None + assert prediction.added_sugars.per_100g is None + assert prediction.added_sugars.per_serving is None + assert prediction.protein.daily_value is None + assert prediction.protein.per_100g is None + assert prediction.protein.per_serving is None + assert prediction.sodium.daily_value is None + assert prediction.sodium.per_100g is None + assert prediction.sodium.per_serving is None + assert prediction.sodium.unit is None + assert len(prediction.nutrients) == 0 diff --git a/tests/product/us/us_mail/__init__.py b/tests/product/us/us_mail/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/product/us/us_mail/test_us_mail_v2.py b/tests/product/us/us_mail/test_us_mail_v2.py new file mode 100644 index 00000000..1858a883 --- /dev/null +++ b/tests/product/us/us_mail/test_us_mail_v2.py @@ -0,0 +1,53 @@ +import json + +import pytest + +from mindee.parsing.common.document import Document +from mindee.parsing.common.page import Page +from mindee.product.us import UsMailV2 +from mindee.product.us.us_mail.us_mail_v2_document import ( + UsMailV2Document, +) +from tests.product import PRODUCT_DATA_DIR + +RESPONSE_DIR = PRODUCT_DATA_DIR / "us_mail" / "response_v2" + +UsMailV2DocumentType = Document[ + UsMailV2Document, + Page[UsMailV2Document], +] + + +@pytest.fixture +def complete_doc() -> UsMailV2DocumentType: + file_path = RESPONSE_DIR / "complete.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(UsMailV2, json_data["document"]) + + +@pytest.fixture +def empty_doc() -> UsMailV2DocumentType: + file_path = RESPONSE_DIR / "empty.json" + with open(file_path, "r", encoding="utf-8") as open_file: + json_data = json.load(open_file) + return Document(UsMailV2, json_data["document"]) + + +def test_complete_doc(complete_doc: UsMailV2DocumentType): + file_path = RESPONSE_DIR / "summary_full.rst" + with open(file_path, "r", encoding="utf-8") as open_file: + reference_str = open_file.read() + assert str(complete_doc) == reference_str + + +def test_empty_doc(empty_doc: UsMailV2DocumentType): + prediction = empty_doc.inference.prediction + assert prediction.sender_name.value is None + assert prediction.sender_address.city is None + assert prediction.sender_address.complete is None + assert prediction.sender_address.postal_code is None + assert prediction.sender_address.state is None + assert prediction.sender_address.street is None + assert len(prediction.recipient_names) == 0 + assert len(prediction.recipient_addresses) == 0