ReceiptSplitAI / image_processing_interface.py
valentynliubchenko
merging
eba303d
from abc import ABC, abstractmethod
from loguru import logger
class ImageProcessingInterface(ABC):
@abstractmethod
def process_image(self, image_base64: str, model_name: str, prompt: str, system: str, temperature: float):
pass
def _validate_receipt_data(self, json_content):
"""
Validates the receipt data to ensure required fields are correctly populated.
:param json_content: The JSON content to validate
:return: True if the required fields are valid, False otherwise
"""
if "total_price" not in json_content or json_content.get("total_price") == "unknown":
return False
if "items" not in json_content or not json_content.get("items"):
return False
return True
def _add_total_price(self, json_content):
"""
Duplicates the value of 'total_price_without_discount' into 'total_price' for each item in the 'items' array.
If 'total_price_without_discount' is missing or equals 'unknown', 'total_price' is set to "0.00".
:param json_content: Dictionary containing the JSON data
:return: Modified JSON content
"""
if "items" in json_content:
for item in json_content["items"]:
total_price_without_discount = item.get("total_price_without_discount")
if total_price_without_discount and total_price_without_discount != "unknown":
item["total_price"] = total_price_without_discount
else:
logger.warning(
f"Item {item.get('name', 'unknown')} has missing or 'unknown' 'total_price_without_discount'. Setting 'total_price' to '0.00'.")
item["total_price"] = "0.00"
return json_content
def _extract_float_value(self, json_content, key, default=0.0):
try:
return float(json_content.get(key, default))
except (ValueError, TypeError):
logger.error(f"Invalid {key} value: {json_content.get(key)}")
return default
def _add_discount_item(self, json_content):
"""
Adds a new "Discount" item to the 'items' array if 'total_discount' is greater than 0.
:param json_content: Dictionary containing the JSON data
:return: Modified JSON content
"""
total_discount = self._extract_float_value(json_content, "total_discount", 0.0)
all_items_price_with_tax = json_content.get("all_items_price_with_tax", "unknown")
if total_discount > 0:
discount_item = {
"name": "Discount",
"quantity": 1.0,
"measurement_unit": "ks",
"total_price_without_discount": -total_discount,
"unit_price": -total_discount,
"total_price_with_discount": -total_discount,
"discount": 0.0,
"category": "Discount",
"item_price_with_tax": all_items_price_with_tax,
"total_price": -total_discount
}
if "items" not in json_content:
json_content["items"] = []
json_content["items"].append(discount_item)
logger.info("Added 'Discount' item to the receipt.")
return json_content
def _add_rounding_item(self, json_content):
"""
Adds a new "Rounding" item to the 'items' array if 'rounding' is not zero.
:param json_content: Dictionary containing the JSON data
:return: Modified JSON content
"""
rounding = self._extract_float_value(json_content, "rounding", 0.0)
if rounding != 0:
all_items_price_with_tax = json_content.get("all_items_price_with_tax", "unknown")
rounding_item = {
"name": "Rounding",
"quantity": 1.0,
"measurement_unit": "ks",
"total_price_without_discount": rounding,
"unit_price": rounding,
"total_price_with_discount": rounding,
"discount": 0.0,
"category": "Rounding",
"item_price_with_tax": all_items_price_with_tax,
"total_price": rounding
}
if "items" not in json_content:
json_content["items"] = []
json_content["items"].append(rounding_item)
logger.info("Added 'Rounding' item to the receipt.")
return json_content