"""JSON response helpers for the procurement API. DynamoDB items come back through boto3 with numeric attributes as ``decimal.Decimal`` (e.g. purchase-orders ``total_amount``/``line_items`` prices), which ``json.dumps`` rejects. The encoder below renders integral Decimals as JSON integers (exact) and non-integral Decimals as floats. For the values this API serves -- currency amounts at PO magnitudes, well under ~15 significant digits -- the shortest-float repr round-trips the original digits exactly. A Decimal carrying more precision than a float can hold (DynamoDB Number supports 38 digits) would be truncated silently; the pipeline never writes such values, but if that ever changes, switch non-integral Decimals to ``str(o)`` and update the OpenAPI number types. """ import decimal import json class _DecimalSafeEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, decimal.Decimal): if o == o.to_integral_value(): return int(o) return float(o) if isinstance(o, set): return sorted(o) return super().default(o) def dumps(payload) -> str: return json.dumps(payload, cls=_DecimalSafeEncoder) def json_response(status_code: int, payload) -> dict: return { "statusCode": status_code, "headers": {"Content-Type": "application/json"}, "body": dumps(payload), } def error_response(status_code: int, message: str) -> dict: return json_response(status_code, {"error": message})