kirana-detective / agents /reconciliation_agent.py
naazimsnh02's picture
Finetuning completed for yolo26n-indian-fmcg-detection and minicpm5-1b-indian-fmcg-normalizer
7b5611f
Raw
History Blame
2.86 kB
from __future__ import annotations
import logging
import time
from typing import List, Tuple
from models import AnomalyFlag, NormalisedInvoice, DeliveryCountMap, AgentTraceEntry
from tracer import make_trace_entry
logger = logging.getLogger(__name__)
AGENT_NAME = "Reconciliation_Agent"
AGENT_VERSION = "1.0.0"
class ReconciliationAgent:
def run(
self,
invoice: NormalisedInvoice,
delivery_count_map: DeliveryCountMap,
audit_run_id: str,
) -> Tuple[List[AnomalyFlag], List[str], AgentTraceEntry]:
t_start = time.monotonic()
flags: List[AnomalyFlag] = []
invoiced_product_ids: set[str] = set()
for item in invoice.items:
if item.product_id is None:
continue
invoiced_product_ids.add(item.product_id)
delivered = delivery_count_map.get(item.product_id, 0)
if item.quantity > delivered:
shortage = item.quantity - delivered
flags.append(AnomalyFlag(
flag_type="delivery_shortage",
product_id=item.product_id,
product_name=item.product_normalized or item.product_raw,
amount_inr=shortage * item.unit_price,
description=(
f"{item.product_normalized or item.product_raw}: "
f"invoiced {item.quantity}, delivered {delivered}, short {shortage}"
),
action_item=(
f"Request delivery of {shortage:.0f} missing "
f"{item.product_normalized or item.product_raw} "
f"or credit note for ₹{shortage * item.unit_price:.2f}"
),
metadata={
"invoice_quantity": item.quantity,
"delivered_quantity": delivered,
"shortage_quantity": shortage,
"unit_price": item.unit_price,
},
))
# Products in delivery photos but NOT on invoice
unexpected = [
pid for pid in delivery_count_map
if pid not in invoiced_product_ids
]
t_end = time.monotonic()
n_flags = len(flags)
n_unexpected = len(unexpected)
trace = make_trace_entry(
agent_name=AGENT_NAME,
agent_version=AGENT_VERSION,
audit_run_id=audit_run_id,
t_start=t_start,
t_end=t_end,
input_summary=(
f"{len(invoice.items)} invoice items; "
f"{len(delivery_count_map)} delivery entries"
),
output_summary=f"{n_flags} shortage flags; {n_unexpected} unexpected deliveries",
)
return flags, unexpected, trace