openapi: 3.0.0
info:
  title: PersonOffice
  version: 2.0.0
  description: >
    A **PersonOffice** represents the assignment of a person to an office.

    It is the entity that links a person (worker) to a work location within the
    same project.


    A person can be assigned to multiple offices, and an office can have
    multiple people assigned to it.


    Use this API to:

    - Assign a person to an office after creating them

    - Find all people assigned to an office (filter by `office_id`)

    - Find all offices a person is assigned to (filter by `person_id`)

    - Look up personal details in the context of their office assignment


    The index and view responses include the person's details and office
    information,

    providing a complete view without additional calls.


    When a PersonOffice is historicized, its child entities (work groups, etc.)
    are automatically

    excluded from normal queries. The `parent_active` field reflects this state.
servers:
  - url: http://service.4hse.com/
security:
  - OAuth2: []
  - AccessToken: []
paths:
  /v2/person-office/index:
    post:
      summary: index
      operationId: indexPersonOffice
      tags:
        - PersonOffices
      description: >
        Returns a paginated list of person-office assignments.


        Most useful filters:

        - `office_id`: all people assigned to a specific office

        - `person_id`: all offices a person is assigned to

        - `person_last_name` + `office_id`: find a person by last name in a
        specific office

        - `person_tax_code`: find by tax code
      requestBody:
        description: Parameters for searching person-office assignments
        required: false
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PersonOfficeIndexParams"
            example:
              filter:
                office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                person_last_name: Smith
              per-page: 50
              page: 1
              sort: person_last_name
      responses:
        "200":
          description: List of person-office assignments
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ViewPersonOffice"
              example:
                - person_office_id: f1a2b3c4-d5e6-7890-abcd-ef1234567890
                  office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                  person_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                  project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                  person_code: JS001
                  person_first_name: John
                  person_last_name: Smith
                  person_tax_code: SMTJHN85C15H501Z
                  person_birth_date: 1985-03-15
                  person_is_employee: true
                  office_name: Rome North Site
                  office_code: RN-001
                  project_name: Acme Construction Ltd
                  project_type: safety
                  owned_active: true
                  parent_active: true
          headers:
            X-Pagination-Current-Page:
              schema:
                type: integer
              description: Current page
            X-Pagination-Page-Count:
              schema:
                type: integer
              description: Total number of pages
            X-Pagination-Per-Page:
              schema:
                type: integer
              description: Number of items per page
            X-Pagination-Total-Count:
              schema:
                type: integer
              description: Total number of items
  /v2/person-office/view/{id}:
    get:
      summary: view
      operationId: viewPersonOffice
      tags:
        - PersonOffices
      description: |
        Retrieves a single person-office assignment by its ID.
      parameters:
        - name: id
          in: path
          description: The person_office_id to retrieve.
          required: true
          schema:
            type: string
            format: uuid
      responses:
        "200":
          description: Person-office assignment found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ViewPersonOffice"
              example:
                person_office_id: f1a2b3c4-d5e6-7890-abcd-ef1234567890
                office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                person_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
                person_code: JS001
                person_first_name: John
                person_last_name: Smith
                person_tax_code: SMTJHN85C15H501Z
                person_birth_date: 1985-03-15
                person_is_employee: true
                office_name: Rome North Site
                office_code: RN-001
                project_name: Acme Construction Ltd
                project_type: safety
                owned_active: true
                parent_active: true
        "404":
          description: Person-office assignment not found
  /v2/person-office/create:
    post:
      summary: create
      operationId: createPersonOffice
      tags:
        - PersonOffices
      description: >
        Creates a new person-office assignment.


        Requires `office_id`, `person_id`, and `project_id`. The
        `person_office_id` is auto-generated if not provided.


        The person and the office must already exist and belong to the same
        project.
      requestBody:
        description: Person-office assignment to create
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PersonOffice"
            example:
              office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
              person_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
              project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
      responses:
        "201":
          description: Person-office assignment created successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PersonOffice"
              example:
                person_office_id: f1a2b3c4-d5e6-7890-abcd-ef1234567890
                office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                person_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
  /v2/person-office/update/{id}:
    put:
      summary: update
      operationId: updatePersonOffice
      tags:
        - PersonOffices
      description: |
        Updates an existing person-office assignment.
      parameters:
        - name: id
          in: path
          description: The person_office_id to update.
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        description: Person-office fields to update
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PersonOffice"
            example:
              office_id: b2c3d4e5-f6a7-8901-bcde-f12345678901
      responses:
        "200":
          description: Person-office assignment updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PersonOffice"
              example:
                person_office_id: f1a2b3c4-d5e6-7890-abcd-ef1234567890
                office_id: b2c3d4e5-f6a7-8901-bcde-f12345678901
                person_id: e3a1f5d2-8c4b-4e7a-9f6d-2b1c3d4e5f6a
                project_id: b5a7d602-3fc9-4e2a-9d1a-6e5b4c8f7a01
        "404":
          description: Person-office assignment not found
  /v2/person-office/delete/{id}:
    delete:
      summary: delete
      operationId: deletePersonOffice
      tags:
        - PersonOffices
      description: >
        Deletes a person-office assignment.


        If `force=false` (default), the operation is interrupted and the
        response lists

        child entities that would be deleted.

        If `force=true`, the assignment and all related entities are deleted.
      parameters:
        - name: id
          in: path
          description: The person_office_id to delete.
          required: true
          schema:
            type: string
            format: uuid
        - name: force
          in: query
          description: If true, deletes the assignment and all child entities. If false,
            returns a preview of affected entities.
          schema:
            type: boolean
            default: false
      responses:
        "204":
          description: Person-office assignment deleted successfully
        "400":
          description: Preview of entities that would be deleted (returned when force=false)
components:
  schemas:
    PersonOffice:
      type: object
      properties:
        person_office_id:
          type: string
          format: uuid
          description: Unique identifier of the assignment. Auto-generated if not provided
            on creation.
        office_id:
          type: string
          format: uuid
          description: The office (work location) the person is assigned to. Pass the
            `office_id` obtained from the Office API.
        person_id:
          type: string
          format: uuid
          description: The person assigned to this office. Pass the `person_id` obtained
            from the Person API.
        project_id:
          type: string
          format: uuid
          description: The project (company) this assignment belongs to. Must be the same
            project as both the person and the office.
      required:
        - office_id
        - person_id
        - project_id
    ViewPersonOffice:
      type: object
      properties:
        person_office_id:
          type: string
          format: uuid
          description: Unique identifier of the assignment.
        office_id:
          type: string
          format: uuid
          description: The office the person is assigned to.
        person_id:
          type: string
          format: uuid
          description: The assigned person.
        project_id:
          type: string
          format: uuid
          description: The project this assignment belongs to.
        person_code:
          type: string
          description: Employee code of the person.
        person_first_name:
          type: string
          description: First name of the person.
        person_last_name:
          type: string
          description: Last name of the person.
        person_is_employee:
          type: boolean
          description: Whether the person is a company employee.
        person_is_external:
          type: boolean
          description: Whether the person is external prevention staff.
        person_street:
          type: string
          description: Residential address.
        person_locality:
          type: string
          description: City.
        person_postal_code:
          type: string
          description: Postal code.
        person_region:
          type: string
          description: Region or province.
        person_country:
          type: string
          description: Country code.
        person_birth_date:
          type: string
          description: Date of birth.
        person_birth_place:
          type: string
          description: Place of birth.
        person_tax_code:
          type: string
          description: Tax code (fiscal code).
        person_note:
          type: string
          description: Free-text notes.
        person_contract_type:
          type: string
          description: Employment contract type.
        person_entity_id:
          type: string
          description: Email of the linked user account.
        person_sex:
          type: string
          description: Sex.
        project_name:
          type: string
          description: Name of the project (company).
        project_type:
          type: string
          enum:
            - safety
            - template
          description: Type of the parent project.
        office_code:
          type: string
          description: Code of the office.
        office_name:
          type: string
          description: Name of the office.
        owned_active:
          type: boolean
          nullable: true
          description: Whether this assignment is currently active in its validity period.
        parent_active:
          type: boolean
          nullable: true
          description: Whether the parent entities (office, person) are currently active.
    PersonOfficeIndexParams:
      type: object
      properties:
        filter:
          $ref: "#/components/schemas/ViewPersonOffice"
        per-page:
          type: integer
          minimum: 1
          default: 100
        page:
          type: integer
          minimum: 1
          default: 1
        sort:
          type: string
          description: Field to sort by. Prefix with minus for descending order (e.g.
            "-person_last_name").
          enum:
            - person_code
            - person_first_name
            - person_last_name
            - person_birth_date
            - person_tax_code
        history:
          type: boolean
          description: If true, includes historicized (no longer active) entries in the
            results. By default only current entries are returned.
      example:
        filter:
          office_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
          person_last_name: Smith
        per-page: 50
        page: 1
        sort: person_last_name
  securitySchemes:
    OAuth2:
      type: oauth2
      flows:
        password:
          tokenUrl: https://auth.4hse.com/realms/4hse/protocol/openid-connect/token
          scopes: {}
    AccessToken:
      type: apiKey
      in: query
      name: access-token
