Atualizar posição por código

Esse endpoint realiza uma atualização completa (substituição) dos dados de uma posição existente. Todos os campos fornecidos no corpo da requisição substituirão os valores atuais da posição.

Regras de negócio e comportamento

1. Campos obrigatórios e existência

Os seguintes campos são obrigatórios e devem referenciar registros existentes na base, mesmo em uma atualização:

  • externalCodeRole: Obrigatório. O cargo deve existir previamente.
  • externalCodeArea: Obrigatório. A área deve existir previamente.

2. Campos opcionais e remoção de vínculos

Para campos opcionais, o comportamento de replace (substituição) é estrito:

  • Remoção de vínculo: Para remover um valor opcional (desvincular), defina explicitamente o campo como null no corpo da requisição.
  • Liderança (externalCodeParent): Opcional. Pode ser definido como null para transformar a posição em uma posição raiz.
  • Unidade Operacional (externalCodeOperationUnit): Opcional. Pode ser definido como null para desvincular.

3. Vínculo de colaborador

  • Atribuição: O preenchimento do colaborador é opcional. Definir o campo como null desvincula o colaborador.
  • Exclusividade: Se um colaborador for atribuído, ele não pode estar vinculado a outra posição ativa simultaneamente.

Exemplo de requisição (cURL)

curl --location 'api.gupy.io/os/v1/positions' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer bearer_token_value_here' \
--data-raw '{   
  "name": "Nome da posição",
  "description": "Descrição da posição",
  "externalCodeCostCenter": "COST_CENTER_CODE",
  "externalCodeArea": "AREA_CODE",
  "externalCodeRole": "CARGO_CODE",
  "externalCodeParent": "PARENT_PISITION_CODE",
  "employeeEmail": "[email protected]",
  "employeeTaxpayerRegistry": null,
  "employeeInternalCompanyNumber": null
}'

Atenção: Forneça o token de autenticação no cabeçalho Authorization.

Possiveis erros

Posição não encontrada

Erro lançado quando a posição não foi encontrada através do externalCode informado.

`{
  "statusCode": 404,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions/{externalCode}",
  "method": "PUT",
  "title": "NotFoundException",
  "message": "Position not found",
  "errors": [
    {
      "code": "POSITION_NOT_FOUND_ERROR",
      "target": "NotFoundException",
      "message": "Position not found"
    }
  ]
}

Área não encontrada

Erro lançado quando a área não foi encontrada através do externalCodeArea informado.

{
  "statusCode": 404,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "NotFoundException",
  "message": "Area not found",
  "errors": [
    {
      "code": "AREA_NOT_FOUND",
      "target": "NotFoundException",
      "message": "Area not found"
    }
  ]
}

Cargo não encontrado

Erro lançado quando o cargo não foi encontrado através do externalCodeRole informado.

{
  "statusCode": 404,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "NotFoundException",
  "message": "Role not found",
  "errors": [
    {
      "code": "ROLE_NOT_FOUND",
      "target": "NotFoundException",
      "message": "Role not found"
    }
  ]
}

Centro de custo não encontrado

Erro lançado quando o centro de custo não foi encontrado através do externalCodeCostCenter informado.

{
  "statusCode": 404,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "NotFoundException",
  "message": "Cost center not found",
  "errors": [
    {
      "code": "COST_CENTER_NOT_FOUND",
      "target": "NotFoundException",
      "message": "Cost center not found"
    }
  ]
}

Liderança não encontrada

Erro lançado quando a posição da liderança não foi encontrada através do externalCodeParent informado.

{
  "statusCode": 404,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "NotFoundException",
  "message": "Parent position not found",
  "errors": [
    {
      "code": "PARENT_POSITION_NOT_FOUND",
      "target": "NotFoundException",
      "message": "Parent position not found"
    }
  ]
}

Colaborador não encontrado

Erro lançado quando o colaborador não foi encontrado através do employeeEmail, employeeTaxpayerRegistry e employeeInternalCompanyNumber informado.

{
  "statusCode": 404,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "NotFoundException",
  "message": "Employee not found",
  "errors": [
    {
      "code": "EMPLOYEE_NOT_FOUND",
      "target": "NotFoundException",
      "message": "Employee not found"
    }
  ]
}

Colaborador alocado em outra posição

Erro lançado quando o colaborador informado está vinculado a outra posição.

{
  "statusCode": 409,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "ConflictException",
  "message": "Employee is already in another position",
  "errors": [
    {
      "code": "EMPLOYEE_ALREADY_ASSIGNED",
      "target": "ConflictException",
      "message": "Employee is already in another position"
    }
  ]
}

Posição raiz (sem liderança) já existe

Erro lançado quando externalCodeParent não é informado, porém já existe uma posição raiz cadastrada na base.

{
  "statusCode": 409,
  "timestamp": "2025-05-29T21:00:00.000Z",
  "path": "/v1/positions",
  "method": "POST",
  "title": "ConflictException",
  "message": "Only one root position allowed per company.",
  "errors": [
    {
      "code": "ALREADY_EXISTS_ROOT_POSITION",
      "target": "ConflictException",
      "message": "Only one root position allowed per company."
    }
  ]
}