Pular para conteúdo

Cities

# Cities

Este documento descreve todas as operações disponíveis para o agregado Cities e seus recursos, seguindo os padrões de Domain-Driven Design (DDD) e Command Query Responsibility Segregation (CQRS).

Índice


Cities (Cidades)

Visão Geral

O agregado City representa as cidades/localidades disponíveis no sistema para prestação de serviços. As cidades podem ser associadas a: - Trabalhos disponíveis (JobCities) - Tarefas específicas de trabalho (JobTaskCities) - Áreas de atuação de profissionais (ProfessionalUserCities) - Endereços de usuários (UserAddresses) - Itens de solicitação (RequestItems)

Commands (Comandos)

1. Criação de Cidade (CreateCity)

Contrato: CreateCityCommand

Campos Necessários:

  • Name (string, obrigatório) - Nome da cidade
  • State (string, obrigatório) - Estado/UF da cidade
  • IsActive (bool, obrigatório) - Indica se a cidade está ativa
  • Author (string, opcional) - Autor da operação

Validações:

  • Name: Não pode ser vazio; Tamanho máximo: 99 caracteres
  • State: Não pode ser vazio; Tamanho máximo: 99 caracteres
  • IsActive: Não pode ser vazio

Retorno: CreateCityResponse - Id (Guid) - Identificador da cidade criada

Handler: CreateCityHandler

Eventos de Domínio:

  • CityCreatedEvent - Disparado quando uma cidade é criada (se implementado)

Regras de Negócio:

  • Não é permitido criar cidades duplicadas (verificação baseada no nome)
  • O nome e estado são automaticamente convertidos para maiúsculas
  • O estado deve ser uma UF válida brasileira (validação através de Address.StateIsValid())
  • Estados aceitos: AC, AL, AP, AM, BA, CE, DF, ES, GO, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SC, SP, SE, TO
  • Se o estado for inválido, retorna mensagem: "Invalid state. State must be one of the following: [lista de UFs]"
  • Cidades inativas não são elegíveis para solicitações de serviço
  • A cidade criada fica imediatamente disponível para associação com jobs e profissionais
  • Se tentar criar uma cidade que já existe, lança exceção AlreadyExistsException

Exemplo de Uso:

{
  "name": "São Paulo",
  "state": "SP",
  "isActive": true,
  "author": "admin@sistema.com"
}

Exemplo de Resposta:

{
  "id": "123e4567-e89b-12d3-a456-426614174000"
}

Nota: Nome e estado serão armazenados como "SÃO PAULO" e "SP" (maiúsculas).


2. Exclusão de Cidade (DeleteCity)

Contrato: DeleteCityCommand

Campos Necessários:

  • Id (Guid, obrigatório) - Identificador da cidade

Validações:

  • Id: Não pode ser vazio

Retorno: Void

Handler: DeleteCityHandler

Regras de Negócio:

  • A cidade deve existir no sistema
  • Verifica se há dependências antes de excluir:
  • JobCities (cidades associadas a trabalhos)
  • JobTaskCities (cidades associadas a tarefas)
  • ProfessionalUserCities (áreas de atuação de profissionais)
  • ProfessionalUserAddresses (endereços de profissionais)
  • UserAddresses (endereços de usuários)
  • RequestItems (itens de solicitação)
  • Se houver dependências, a exclusão pode ser impedida

Recomendação: Considere usar inativação (IsActive = false) em vez de exclusão para manter integridade histórica.


3. Atualização de Cidade (UpdateCity)

Contrato: UpdateCityCommand

Campos Necessários:

  • Id (Guid, obrigatório) - Identificador da cidade (JsonIgnore)
  • Name (string, obrigatório) - Nome da cidade
  • State (string, obrigatório) - Estado/UF da cidade
  • IsActive (bool, obrigatório) - Indica se a cidade está ativa
  • Observation (string, opcional) - Observações adicionais
  • Author (string, opcional) - Autor da operação

Validações:

  • Id: Não pode ser vazio; Cidade deve existir
  • Name: Não pode ser vazio; Tamanho máximo: 99 caracteres
  • State: Não pode ser vazio; Tamanho máximo: 99 caracteres; Deve ser UF válida
  • IsActive: Não pode ser vazio

Retorno: Void

Handler: UpdateCityHandler

Regras de Negócio:

  • A cidade deve existir no sistema
  • O nome e estado são automaticamente convertidos para maiúsculas
  • O estado deve ser uma UF válida brasileira
  • Atualizar IsActive para false desativa a cidade para novas solicitações
  • Cidades com pedidos em andamento devem permanecer ativas até conclusão

Exemplo de Uso:

{
  "name": "São Paulo",
  "state": "SP",
  "isActive": false,
  "observation": "Cidade temporariamente desativada",
  "author": "admin@sistema.com"
}

Queries (Consultas)

1. Buscar Cidade por ID (GetCityById)

Contrato: GetCityByIdQuery

Campos Necessários:

  • Id (Guid, obrigatório) - Identificador da cidade

Retorno: GetCityByIdResponse - Id (Guid) - Identificador da cidade - Name (string) - Nome da cidade - State (string) - Estado/UF - IsActive (bool) - Status ativo/inativo - CreatedAt (DateTime) - Data de criação - UpdatedAt (DateTime?) - Data da última atualização - AuthorCreated (string) - Autor da criação - AuthorUpdated (string) - Autor da última atualização

Handler: GetCityByIdHandler

Mapper: GetCityByIdMapper

Descrição:

  • Retorna todos os dados da cidade especificada
  • Inclui informações de auditoria (datas e autores)
  • Se a cidade não existir, lança exceção NotFound

Regras de Negócio:

  • Retorna todos os dados da cidade
  • Inclui informações de auditoria
  • Se a cidade não existir, lança exceção NotFound

Exemplo de Resposta:

{
  "id": "123e4567-e89b-12d3-a456-426614174000",
  "name": "SÃO PAULO",
  "state": "SP",
  "isActive": true,
  "createdAt": "2025-01-08T10:30:00Z",
  "updatedAt": "2025-01-08T15:45:00Z",
  "authorCreated": "admin@sistema.com",
  "authorUpdated": null
}

2. Pesquisar Cidades (SearchCities)

Contrato: SearchCitiesQuery

Campos Opcionais: - State (string, opcional) - Filtrar por estado/UF - Name (string, opcional) - Filtrar por nome da cidade - IsActive (bool?, opcional) - Filtrar por status ativo/inativo - PostalCode (string, opcional) - Filtrar por CEP - JobId (Guid?, opcional) - Filtrar cidades associadas a um trabalho específico - JobTaskId (Guid?, opcional) - Filtrar cidades associadas a uma tarefa específica

Retorno: SearchCitiesResponse - Lista de cidades que atendem aos critérios de filtro - Cada item contém os dados completos da cidade Descrição:

  • Retorna uma lista de cidades conforme os filtros aplicados
  • Permite busca por estado, nome, status e associações com jobs

Handler: SearchCitiesHandler

Mapper: SearchCitiesMapper

Regras de Negócio:

  • Quando nenhum filtro é fornecido, retorna todas as cidades ativas
  • State: Busca exata, case-insensitive
  • Name: Realiza busca parcial, case-insensitive (LIKE)
  • IsActive:
  • true - apenas cidades ativas
  • false - apenas cidades inativas
  • null - todas as cidades
  • PostalCode: Busca cidades que atendem um CEP específico
  • JobId: Retorna cidades onde um trabalho específico está disponível
  • JobTaskId: Retorna cidades onde uma tarefa específica pode ser executada
  • Filtros podem ser combinados para buscas mais específicas

Exemplo de Uso:

// Buscar todas as cidades ativas de São Paulo
{
  "state": "SP",
  "isActive": true
}

// Buscar cidades por nome parcial
{
  "name": "Santo"
}

// Buscar cidades onde um job está disponível
{
  "jobId": "123e4567-e89b-12d3-a456-426614174000"
}

Exemplo de Resposta:

{
  "cities": [
    {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "name": "SÃO PAULO",
      "state": "SP",
      "isActive": true,
      "createdAt": "2025-01-08T10:30:00Z"
    },
    {
      "id": "456e7890-e12b-34d5-b678-901234567890",
      "name": "SANTO ANDRÉ",
      "state": "SP",
      "isActive": true,
      "createdAt": "2025-01-07T09:15:00Z"
    },
    {
      "id": "789fabcd-e34f-56a7-c890-123456789012",
      "name": "SANTOS",
      "state": "SP",
      "isActive": true,
      "createdAt": "2025-01-06T14:20:00Z"
    }
  ]
}

Conceitos de DDD e CQRS

Domain-Driven Design (DDD)

Aggregate Root: - City é um agregado raiz independente - Mantém consistência de suas propriedades - Possui coleções de entidades relacionadas (JobCities, JobTaskCities, ProfessionalUserCities, ProfessionalUserAddresses, UserAddresses, RequestItems) - Constantes de domínio: - MaxNameLength = 99 - MaxStateLength = 2

Value Objects: - Author - Representa o autor da operação

Domain Methods: - Validate() - Valida se a cidade está ativa e elegível para solicitações - Lança RuleViolationDomainException se a cidade não estiver ativa

Invariantes: - Nome não pode exceder 99 caracteres - Estado não pode exceder 2 caracteres e deve ser uma UF válida - Nome e estado são convertidos para maiúsculas - Cidade deve estar ativa para aceitar solicitações

Domain Exceptions: - RuleViolationDomainException - Quando regras de negócio são violadas - AlreadyExistsDomainException - Quando tenta criar cidade duplicada - NotFoundDomainException - Quando cidade não é encontrada

CQRS (Command Query Responsibility Segregation)

Commands (Comandos): - CreateCityCommand - Cria uma nova cidade - DeleteCityCommand - Remove uma cidade existente - Todos os comandos passam por validação (FluentValidation) - Cada comando tem um handler dedicado que executa a lógica de negócio - Comandos modificam o estado do sistema

Queries (Consultas): - GetCityByIdQuery - Busca uma cidade específica - SearchCitiesQuery - Pesquisa cidades com filtros - Queries são otimizadas para leitura - Não modificam o estado do sistema - Cada query tem um handler e mapper dedicados - Podem incluir joins com outras entidades para otimização

Validators: - CreateCityValidator - Valida dados de criação - DeleteCityValidator - Valida dados de exclusão - Utilizam FluentValidation para regras declarativas


Relacionamentos

JobCity

Representa a associação entre uma cidade e um trabalho disponível. - Um trabalho pode estar disponível em múltiplas cidades - Define a área de cobertura do serviço

JobTaskCity

Representa a associação entre uma cidade e uma tarefa específica. - Permite granularidade maior: algumas tarefas podem não estar disponíveis em todas as cidades de um job - Controla disponibilidade regional de serviços específicos

ProfessionalUserCity

Representa áreas de atuação de profissionais. - Define em quais cidades o profissional presta serviço - Usado para matching geográfico

ProfessionalUserAddress

Endereços de profissionais vinculados a cidades. - Todo endereço de profissional está associado a uma cidade - Usado para validação geográfica e cálculo de distância para serviços

UserAddress

Endereços de usuários vinculados a cidades. - Todo endereço está associado a uma cidade - Usado para validar elegibilidade de serviços

RequestItem

Itens de solicitação vinculados a cidades. - Cada solicitação é feita para uma cidade específica - A cidade deve estar ativa e associada ao job solicitado


Validações de Domínio

Método Validate()

public void Validate()
{
    if (!IsActive)
    {
        throw new RuleViolationDomainException("City not eligible for requests.");
    }
}

Este método é chamado durante o processamento de solicitações para garantir que apenas cidades ativas aceitem novos pedidos.


Observações Importantes

  1. Normalização de Dados: Nome e estado são convertidos para maiúsculas automaticamente para consistência
  2. Auditoria: Todas as operações registram autor e data
  3. Status Ativo: Apenas cidades ativas podem:
  4. Receber novas solicitações
  5. Ser associadas a novos jobs
  6. Aparecer em buscas padrão de usuários
  7. Integridade Referencial: Verifique dependências antes de excluir
  8. Unicidade: Sistema previne criação de cidades duplicadas
  9. Granularidade Regional:
  10. Use JobCity para disponibilidade geral do trabalho
  11. Use JobTaskCity quando tarefas específicas têm disponibilidade regional diferente
  12. CEP: O filtro por PostalCode requer integração com sistema de endereços/CEPs