Saltar al contenido principal

Service Types Module

Overview

The Service Types module manages categorizable service types within a business. Each service type is scoped to a single business (multi-tenant) and can be activated or deactivated.

Examples: "Food Tour", "Cooking Class", "Private Tour", "Cultural Experience".

Architecture

Follows hexagonal architecture (ports & adapters):

service-types/
├── service-types.module.ts # NestJS module
├── application/
│ └── service-types.service.ts # Use cases
├── domain/
│ └── service-types-repository.domain.ts # Repository port (interface + DI token)
├── infrastructure/
│ └── service-types.repository.ts # Kysely adapter (implements port)
└── interfaces/
├── service-types.controller.ts # HTTP controller
├── dtos/
│ ├── create-service-type.dto.ts
│ └── update-service-type.dto.ts
└── query/
└── paginate-service-types.query.ts

Dependency Flow

Controller → Service → IServiceTypesRepository (port)

ServiceTypesRepository (adapter)

The service depends on the domain interface, not the concrete repository. Injection is via SERVICE_TYPES_REPOSITORY Symbol token.

Domain Model

ServiceType entity:

FieldTypeDescription
idUUIDAuto-generated primary key
namestringService type name
businessIdUUIDOwning business (multi-tenant)
isActivebooleanActive/inactive flag
createdByUUIDUser who created
updatedByUUID?User who last updated
createdAttimestampAuto-generated
updatedAttimestampAuto-updated on changes

API Endpoints

All endpoints require Bearer authentication and ServiceType resource permission.

POST /service-types

Create a new service type.

Body:

{
"name": "Food Tour",
"businessId": "uuid",
"isActive": true,
"createdBy": "uuid"
}

GET /service-types

List service types with pagination, search, and sorting.

Required query: businessId Optional query: page, size, search, orderBy (name), order (asc/desc)

GET /service-types/:id

Get a single service type by ID.

Required query: businessId

PATCH /service-types/:id

Partially update a service type.

Body:

{
"name": "Updated Name",
"updatedBy": "uuid",
"businessId": "uuid"
}

DELETE /service-types/:id

Delete a service type.

Required query: businessId

Security

  • Authentication: Firebase token (global AuthGuard)
  • Authorization: RolesGuard + CASL permission checks
  • Resource: PolicyResource.ServiceType
  • Multi-tenancy: All queries scoped by businessId

Design Decisions

  1. businessId required on all operations — prevents cross-tenant data access
  2. Transaction support — repository methods accept optional Transaction<DB> for composability
  3. Delete returns void — consistent with addresses module; throws if not found
  4. Update DTO omits immutable fieldsbusinessId and createdBy cannot be changed through the update body; businessId is sent separately for scoping