Improve CarPass product UX and service flows

This commit is contained in:
VPN SaaS Dev
2026-05-14 19:33:25 +09:00
parent b85db333d8
commit caa5f6d3db
36 changed files with 1836 additions and 366 deletions

View File

@@ -29,6 +29,7 @@ class OCRCandidateRead(BaseModel):
class OCRResultRead(BaseModel):
recognized_text: str
candidates: list[OCRCandidateRead]
provider: str = "heuristic"
@router.post("/parse-text-receipt", response_model=ReceiptSuggestion)
@@ -39,16 +40,23 @@ async def parse_text_receipt(
content = await file.read()
content_type = (file.content_type or "").lower()
if content_type.startswith("image/") or content_type == "application/pdf":
return ReceiptSuggestion(
confidence=0,
message="OCR по фото/PDF пока не подключен. Загрузите текстовый чек или заполните поля вручную.",
)
result = await get_ocr_provider().recognize(content, file.filename)
if not result.recognized_text:
return ReceiptSuggestion(
confidence=0,
message="Не удалось уверенно распознать чек. Открылся ручной ввод: проверьте дату, сумму, литры и цену.",
)
return parse_receipt_text(result.recognized_text)
text = " ".join(
[
file.filename or "",
content.decode("utf-8", errors="ignore"),
]
)
return parse_receipt_text(text)
def parse_receipt_text(text: str) -> ReceiptSuggestion:
normalized = text.replace("\xa0", " ").replace(",", ".")
compact = re.sub(r"\s+", " ", normalized).strip()
numbers = [Decimal(item) for item in re.findall(r"\d+(?:\.\d+)?", compact)]
@@ -102,6 +110,7 @@ async def recognize_license_plate(
return OCRResultRead(
recognized_text=result.recognized_text,
candidates=[OCRCandidateRead(**item.__dict__) for item in result.candidates if item.type == "license_plate"],
provider=result.provider,
)
@@ -114,6 +123,7 @@ async def recognize_vin(
return OCRResultRead(
recognized_text=result.recognized_text,
candidates=[OCRCandidateRead(**item.__dict__) for item in result.candidates if item.type == "vin"],
provider=result.provider,
)
@@ -126,6 +136,7 @@ async def recognize_service_document(
return OCRResultRead(
recognized_text=result.recognized_text,
candidates=[OCRCandidateRead(**item.__dict__) for item in result.candidates],
provider=result.provider,
)