"""Response mappers for converting models to API response schemas.""" from models import Exchange, Invite, PriceHistory from schemas import ( AdminExchangeResponse, ExchangeResponse, ExchangeUserContact, InviteResponse, PriceHistoryResponse, ) class ExchangeMapper: """Mapper for Exchange model to response schemas.""" @staticmethod def to_response( exchange: Exchange, user_email: str | None = None, ) -> ExchangeResponse: """Convert an Exchange model to ExchangeResponse schema.""" email = user_email if user_email is not None else exchange.user.email return ExchangeResponse( id=exchange.id, public_id=str(exchange.public_id), user_id=exchange.user_id, user_email=email, slot_start=exchange.slot_start, slot_end=exchange.slot_end, direction=exchange.direction.value, bitcoin_transfer_method=exchange.bitcoin_transfer_method.value, eur_amount=exchange.eur_amount, sats_amount=exchange.sats_amount, market_price_eur=exchange.market_price_eur, agreed_price_eur=exchange.agreed_price_eur, premium_percentage=exchange.premium_percentage, status=exchange.status.value, created_at=exchange.created_at, cancelled_at=exchange.cancelled_at, completed_at=exchange.completed_at, ) @staticmethod def to_admin_response(exchange: Exchange) -> AdminExchangeResponse: """Convert an Exchange model to AdminExchangeResponse with user contact.""" user = exchange.user return AdminExchangeResponse( id=exchange.id, public_id=str(exchange.public_id), user_id=exchange.user_id, user_email=user.email, user_contact=ExchangeUserContact( email=user.email, contact_email=user.contact_email, telegram=user.telegram, signal=user.signal, nostr_npub=user.nostr_npub, ), slot_start=exchange.slot_start, slot_end=exchange.slot_end, direction=exchange.direction.value, bitcoin_transfer_method=exchange.bitcoin_transfer_method.value, eur_amount=exchange.eur_amount, sats_amount=exchange.sats_amount, market_price_eur=exchange.market_price_eur, agreed_price_eur=exchange.agreed_price_eur, premium_percentage=exchange.premium_percentage, status=exchange.status.value, created_at=exchange.created_at, cancelled_at=exchange.cancelled_at, completed_at=exchange.completed_at, ) class InviteMapper: """Mapper for Invite model to response schemas.""" @staticmethod def to_response(invite: Invite) -> InviteResponse: """Build an InviteResponse from an Invite with loaded relationships.""" return InviteResponse( id=invite.id, identifier=invite.identifier, godfather_id=invite.godfather_id, godfather_email=invite.godfather.email, status=invite.status.value, used_by_id=invite.used_by_id, used_by_email=invite.used_by.email if invite.used_by else None, created_at=invite.created_at, spent_at=invite.spent_at, revoked_at=invite.revoked_at, ) class PriceHistoryMapper: """Mapper for PriceHistory model to response schemas.""" @staticmethod def to_response(record: PriceHistory) -> PriceHistoryResponse: """Convert a PriceHistory model to PriceHistoryResponse schema.""" return PriceHistoryResponse( id=record.id, source=record.source, pair=record.pair, price=record.price, timestamp=record.timestamp, created_at=record.created_at, )