Skip to content

[BE] TechTix Gateway Integration #137

Description

@jlorion

Context

The DurianPy Badge System relies on TechTix as the authoritative external source of truth for community meetup events. To register badge design blueprints and verify participant or speaker badge issuances, the badge backend requires verified meetup details (name, date, venue) retrieved by entryId. Following Clean Architecture, this integration must be abstracted behind an outbound application port (TechTixGatewayPort) and implemented via an infrastructure HTTP adapter (TechTixHttpGateway), ensuring third-party network concerns do not bleed into domain models and use cases while enabling easy mocking in automated tests.

Important Details

  • User Story: As a backend service, I want to retrieve verified meetup event details from the TechTix API by entry ID, so that badge designs and issuances can be accurately linked to authoritative event snapshots.
  • Task: Implement TechTixGatewayPort outbound interface, domain exceptions, and TechTixHttpGateway HTTP adapter calling GET /events/{entryId} with Bearer API key authentication, extracting only the necessary meetup attributes into MeetupDetailDTO while discarding extraneous ticketing payload data.

Sample Request / Input Payload

// Sample Request (GET /events/{entryId})
GET /events/9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d HTTP/1.1
Host: api.techtix.org
Authorization: Bearer <TECHTIX_API_KEY>

Sample Response / Output Payload

200 OK
// Sample Response (200 OK - TechTix Raw Event Payload)
{
  "name": "DurianPy September 2026 Meetup",
  "description": "Monthly community meetup for Python developers in Davao.",
  "email": "organizers@durianpy.org",
  "startDate": "2026-09-26T18:00:00.000Z",
  "endDate": "2026-09-26T21:00:00.000Z",
  "venue": "Davao City Tech Hub",
  "paidEvent": false,
  "price": 0,
  "bannerLink": "https://cdn.techtix.org/banners/banner.png",
  "logoLink": "https://cdn.techtix.org/logos/logo.png",
  "certificateTemplate": "cert-tpl-default",
  "isApprovalFlow": false,
  "isLimitedSlot": true,
  "maximumSlots": 100,
  "status": "published",
  "hasMultipleTicketTypes": false,
  "konfhubId": "konf-12345",
  "konfhubApiKey": "secret-key-xyz",
  "platformFee": 0,
  "sprintDay": false,
  "sprintDayPrice": 0,
  "maximumSprintDaySlots": 0,
  "sprintDayRegistrationCount": 0,
  "ticketTypes": [
    {
      "name": "General Admission",
      "description": "Standard attendee access",
      "tier": "regular",
      "originalPrice": 0,
      "price": 0,
      "maximumQuantity": 100,
      "eventId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
      "konfhubId": "konf-12345",
      "currentSales": 42
    }
  ],
  "gcashQRCode": "https://cdn.techtix.org/qr/gcash.png",
  "gcashName": "DurianPy Community",
  "gcashNumber": "09171234567",
  "registrationCount": 42,
  "dailyEmailCount": 10,
  "lastEmailSent": "2026-09-14T18:05:06.261Z",
  "eventId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "createDate": "2026-09-01T10:00:00.000Z",
  "updateDate": "2026-09-14T18:05:06.261Z",
  "createdBy": "user-admin-1",
  "updatedBy": "user-admin-1",
  "bannerUrl": "https://cdn.techtix.org/banners/banner.png",
  "logoUrl": "https://cdn.techtix.org/logos/logo.png",
  "certificateTemplateUrl": "https://cdn.techtix.org/templates/cert.pdf"
}
Extracted Application DTO (MeetupDetailDTO)
// Extracted MeetupDetailDTO (Only essential fields retained)
{
  "meetup_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
  "name": "DurianPy September 2026 Meetup",
  "date": "2026-09-26T18:00:00.000Z",
  "venue": "Davao City Tech Hub"
}
404 Not Found
// Sample Response (404 Not Found)
{
  "error": "EventNotFound",
  "message": "Event with entryId 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d does not exist."
}

Scope

In-Scope:

  • Define abstract outbound port TechTixGatewayPort in src/application/ports/gateways/techtix_gateway_port.py.
  • Define domain exceptions TechTixGatewayError and TechTixEventNotFoundError in src/domain/exceptions/techtix_exceptions.py.
  • Export new domain exceptions in src/domain/exceptions/__init__.py.
  • Implement TechTixHttpGateway in src/infrastructure/gateway/techtix_http_gateway.py using httpx to query GET /events/{entryId} with Authorization: Bearer <TECHTIX_API_KEY>.
  • Extract only required meetup fields (meetup_id from eventId or {entryId}, name from name, date from startDate, and venue from venue) into MeetupDetailDTO.
  • Discard all extraneous ticketing, pricing, payment, and external platform metadata (such as ticketTypes, gcashNumber, konfhubApiKey, platformFee, and certificateTemplate) at the gateway boundary.
  • Add configuration settings TECHTIX_API_BASE_URL and TECHTIX_API_KEY in src/core/settings.py.
  • Intercept HTTP status codes: translate 404 Not Found to TechTixEventNotFoundError; translate 5xx server errors or network timeouts to TechTixGatewayError.
  • Mask sensitive API keys and authorization headers using mask_string in logging statements.
  • Provide FastAPI dependency injection provider in src/presentation/api/dependencies/techtix_dependencies.py.
  • Write accompanying unit tests using mocked HTTP responses to verify contract handling, selective field mapping, and error translations.

Out-of-Scope:

  • Parsing, validating, or storing ticketing tiers, pricing, or payment details from the TechTix response.
  • Managing attendee ticket registrations, webhooks, or event lifecycle operations in TechTix.

Files to Edit

  • src/domain/exceptions/techtix_exceptions.py: Define TechTixGatewayError and TechTixEventNotFoundError inheriting from DomainError and EntityNotFoundError.
  • src/domain/exceptions/__init__.py: Re-export TechTixGatewayError and TechTixEventNotFoundError.
  • src/application/ports/gateways/techtix_gateway_port.py: Define abstract TechTixGatewayPort with get_meetup_details(meetup_id: str) -> MeetupDetailDTO.
  • src/application/dtos/badge_design_dto.py: Verify MeetupDetailDTO structure (meetup_id, name, date, venue).
  • src/core/settings.py: Add TECHTIX_API_BASE_URL and TECHTIX_API_KEY configuration fields with environment variable loading.
  • src/infrastructure/gateway/techtix_http_gateway.py: Implement TechTixHttpGateway with httpx.Client, selective field mapping to MeetupDetailDTO, error translation, and token masking.
  • src/presentation/api/dependencies/techtix_dependencies.py: Implement dependency injection provider get_techtix_gateway() -> TechTixGatewayPort.
  • Accompanying unit tests: Write comprehensive unit test suites covering TechTixHttpGateway with mocked HTTP responses and error conditions.

Acceptance Criteria

  • TechTixGatewayPort interface defines get_meetup_details(meetup_id: str) -> MeetupDetailDTO.
  • TechTixHttpGateway executes GET /events/{entryId} with Authorization: Bearer <TECHTIX_API_KEY>.
  • Only required meetup fields (meetup_id, name, date, venue) are extracted into MeetupDetailDTO, ignoring all extraneous ticketing, pricing, and payment metadata.
  • When TechTix API returns HTTP 404 Not Found, the adapter catches it and raises domain TechTixEventNotFoundError.
  • When TechTix API returns HTTP 5xx or connection times out, the adapter catches it and raises domain TechTixGatewayError.
  • Outbound HTTP requests attach authorization credentials using TECHTIX_API_KEY loaded from Settings.
  • Sensitive tokens and authorization headers are masked using mask_string in all log messages.
  • Private instance members, methods, and constants follow the double underscore (__) naming convention.
  • Comprehensive accompanying unit tests pass using mocked HTTP transport without requiring live network access.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions