CSV 가져오기 매핑

가져오기 구성 개요

CSV 가져오기 통합 기능을 사용하면 플랫 CSV 파일에서 연결된 Targetprocess 엔티티의 계층 구조로 데이터를 가져올 수 있습니다. 따라서 모든 가져오기 구성에 앞서 ATP의 데이터 및 데이터 모델의 현재 상태와 가져오기 후 예상되는 데이터의 상태에 대한 심층 분석이 선행되어야 합니다.

실행된 가져오기는 자동으로 롤백할 수 없으므로 데이터의 작은 하위 집합을 사용하여 일부 초기 가져오기를 수행하는 것이 좋습니다.

가져오기 작업의 결과에 영향을 미치는 세 가지 주요 요인이 있습니다:

  1. Targetprocess 의 초기 상태입니다:

    Targetprocess 는 필드, 연결 및 유효성 검사 규칙이 있는 연결된 엔티티 집합을 정의합니다. Targetprocess 에 정의된 모든 설정은 새 데이터를 추가할 수 있는 방식에 영향을 줍니다.

  2. CSV 파일의 내용입니다:

    CSV 파일은 데이터 행으로 구성된 플랫 데이터 세트가 포함된 파일입니다. 모든 행은 구분 기호로 열로 나뉩니다. CSV 가져오기 통합을 사용하려면 첫 번째 행이 열 이름을 정의하는 헤더 행이어야 합니다.

  3. 매핑:

    Targetprocess 상태 및 CSV 파일은 미리 정의되어 있으며 비교적 변경할 수 없습니다. 매핑은 가져오기 프로세스에 영향을 미치는 주요 구성 포인트입니다. 매핑은 플랫 CSV 데이터를 계층적 Target프로세스 연결 엔티티 구조로 변환하는 프로세스를 설명하는 JSON 형식입니다.

매핑 정의

매핑은 표준 구조의 JSON 문서입니다:

{ "entitiesMappings": [] "relations": [ ], }

항목 정의 매핑하기:

  • entitiesMappings - 이 섹션에서는 CSV 레코드가 Targetprocess 에 어떻게 반영되어야 하는지 설명합니다. 모든 매핑에는 참조로 사용할 수 있는 고유한 이름을 가질 수 있습니다. 덕분에 동일한 엔티티 유형에 대해 여러 개의 매핑을 만들 수 있습니다.
  • 관계 - 이 섹션에서는 Targetprocess 엔티티 간의 관계/연결을 정의할 수 있습니다. 관계 섹션에서는 플랫 CSV 데이터 행을 계층적으로 연결된 Targetprocess 엔티티로 변환하는 데 필요한 모든 변환에 대해 설명합니다.

모든 매핑 정의는 CSV 파일의 열을 기반으로 합니다. Targetprocess 의 엔티티에 대한 내부 정의는 메타데이터에서 찾을 수 있습니다: your-account-name.tpondemand.com/api/v1/index/meta

매핑 정의에 반영할 수 있는 사용 사례는 다음과 같습니다.

단일 엔티티 유형 가져오기

단일 엔티티 가져오기는 CSV 가져오기의 가장 간단한 사용 사례입니다. CSV 파일은 단일 Targetprocess 엔티티의 필드로 취급할 수 있는 열 집합을 정의합니다.

CSV 파일의 열 이름은 Targetprocess 엔티티의 필드 이름과 다를 수 있습니다. CSV 열과 Targetprocess 필드 간의 연결은 엔티티 매핑에서 정의해야 합니다:
{ 
  "entitiesMappings": [
    {
      "name": "UserStory",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory.Name"
        },
        {
          "tpFieldName": "Description",
          "csvColumnName": "UserStory.Description"
        }
      ]
    }
  ]
}

엔티티 매핑 속성의 정의:

  • 이름 : 매핑의 고유 이름으로 설정해야 합니다. 모든 가치를 가질 수 있습니다. 매핑 정의를 식별하는 데 사용됩니다.
  • tpEntityTypeName : Targetprocess 엔티티의 이름입니다.
  • 필드매핑 : CSV 열과 Targetprocess 필드 간의 매핑 목록입니다. 모든 필드 매핑은 최소 두 가지 주요 속성으로 구성됩니다:
    • csvColumnName - 소스 CSV 파일의 헤더 행에 정의된 열의 이름입니다.
    • tpFieldName - Targetprocess 필드의 이름입니다. 가져오기 프로세스는 해당 CSV 열에서 값을 읽고 지정된 Targetprocess 필드에 데이터를 유지합니다

검색

CSV 레코드를 가져올 때마다 Targetprocess 엔티티가 업데이트되거나 생성됩니다. 가져오기 메커니즘은 사용자가 동일한 소스 데이터 집합을 사용하여 가져오기를 다시 실행하는 경우 중복된 엔티티를 생성합니다. 매핑 정의에서 조회 키를 지정하면 해당 레코드가 이미 존재하고 대신 업데이트할 수 있는지, 업데이트해야 하는지 확인하여 중복된 레코드 생성을 방지할 수 있습니다.

가져오기 프로세스는 필드가 조회로 표시된 경우 기존 레코드를 검색합니다. 레코드를 찾을 수 없는 경우 새 엔티티가 생성되고, 그렇지 않은 경우 업데이트가 적용됩니다.

복합 조회는 여러 필드에 대해 " isLookup” 을 참으로 설정하여 지정할 수 있습니다.
{
  "entitiesMappings": [
    {
      "name": "UserStoryMappingName",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory.Name"
        },
        {
          "tpFieldName": "Description",
          "csvColumnName": "UserStory.Description"
        },
      ]
    }
  ]
}
설정에 따라 키 동작을 조회합니다:
  • 하나 이상의 쌍이 있어야 합니다: TP 필드-CSV 열의 조회 키가 "true"로 설정되어 있어야 합니다.
  • 조회 키가 "true"로 설정되어 있고 CSV 파일에 동일한 키를 가진 레코드가 두 개 이상 있는 경우(예: feature.name ), 첫 번째 행의 데이터만 가져옵니다. 나머지 행은 무시됩니다.
  • IsLookup 관계를 설정할 수도 있습니다. 예시와 함께 자세한 내용은 '관계' 섹션에서 확인할 수 있습니다.
  • 기본적으로 모든 조회는 대소문자를 구분합니다. 필드(예: user.email )를 대소문자를 구분하지 않도록 변경하려면 필드 매핑에 "isCaseSensitiveLookup": false를 추가해야 합니다.
  • 예외: 'isLookup' 의 동작은 엔티티 ID에 설정된 경우와 다릅니다. Targetprocess 에 이미 존재하는 엔티티는 업데이트되지만 새 엔티티는 생성되지 않습니다. ID 필드는 엔티티 생성 시 시스템에 의해 자동으로 설정되며 수동으로 설정하거나 변경할 수 없기 때문입니다.

하나의 CSV 행에 여러 엔티티

단일 CSV 행에는 여러 엔티티에 대한 데이터가 포함될 수 있습니다. 다음 매핑은 단일 CSV 행을 여러 개의 Targetprocess 엔티티로 가져오는 메커니즘을 정의합니다:

{
  "entitiesMappings": [
    {
      "name": "UserStoryMapping",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory.Name"
        }
      ]
    },
    {
      "name": "TaskMapping",
      "tpEntityTypeName": "Task",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "Task.Email"
        }
      ]
    }
  ]
}

관계

Targetprocess 의 엔티티는 다른 엔티티를 참조할 수 있으며 CSV 파일 구조는 플랫입니다. 이러한 변환을 정의하기 위해 관계의 개념이 도입되었습니다.
{
  "relations": [...],
  "entitiesMappings": [...]
}
모든 관계는 엔티티 매핑이 서로 연관되는 방식을 설명합니다. 항상 '조인' 엔티티 매핑과 에지가 있습니다. 최소 하나의 가장자리가 필요합니다:
{
  "relations": [
    {
      "root": {
        "mappingName": "UserStoryMapping"
      },
      "edges": [
        {
          "field": "Epic",
          "mappingName": "EpicMapping"
        },
        {
          "field": "Project",
          "mappingName": "ProjectMapping"
        }
      ]
    }
  ],
  "entitiesMappings": [
    {
      "name": "UserStoryMapping",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [...]
    },
    {
      "name": "EpicMapping",
      "tpEntityTypeName": "Epic",
      "fieldsMappings": [...]
    },
    {
      "name": "ProjectMapping",
      "tpEntityTypeName": "Project",
      "fieldsMappings": [...]
    }

  ]
}

상수 참조

상수 참조는 모든 CSV 파일 레코드에 동일한 엔티티를 할당하는 데 사용됩니다. 할당하려는 엔티티의 식별자에 대한 지식이 필요합니다. "Awesome Project"라는 프로젝트에 할당될 UserStories 을 가져온다고 가정해 보겠습니다. 먼저 프로젝트 ID( 1008.Then )를 확인합니다 UserStories

UserStory 이름
UserStory1
UserStory2
UserStory3
UserStory4

매핑에서 상수 참조로 채워질 필드(프로젝트)를 지정해야 합니다.

{
  "entitiesMappings": [
    {
      "name": "UserStoryMapping",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory.Name"
        },
        {
          "kind": "ConstantReference",
          "constValue": {
            "id": 1008
          },
          "tpFieldName": "Project"
        }
      ]
    }
  ] 
}

다른 엔티티에 대한 참조(1-M)

일대다 관계는 하나의 엔티티(루트)가 하나 이상의 엔티티(에지)와 연결될 수 있음을 의미합니다. 예를 들어 Targetprocess 에서 프로젝트는 하나 이상의 사용자 스토리와 연결될 수 있으므로 여기에는 일대다 관계가 있습니다. 다음 CSV 파일을 가져온다고 가정해 보겠습니다:

UserStory_Name 프로젝트_이름
UserStory1 Project1
UserStory2 Project1
UserStory3 Project2
UserStory4 Project3

모든 UserStory 은 동일한 row.To 에서 프로젝트와 연결되어야 하며, 이를 위해서는 UserStory ( UserStoryMapping )와 프로젝트( ProjectMapping )에 적절한 필드 매핑을 추가해야 합니다. 다음 단계로 루트 및 에지 엔티티를 추가합니다.

Project를 UserStory 에 추가하려고 합니다. 따라서 mappingName 을 엣지에 넣습니다. 또한 UserStory 에서 프로젝트를 할당하고 에지 엔티티에 추가하는 데 사용할 필드를 지정해야 합니다. 이 경우에는 프로젝트입니다.

마지막 단계로 다른 엔티티가 루트로 할당되므로 UserStory 을 루트로 추가합니다. 전체 매핑은 다음과 같습니다:
{
  "relations": [
    {
      "root": {
        "mappingName": "UserStoryMapping"
      },
      "edges": [
        {
          "mappingName": "ProjectMapping",  
          "field": "Project"
        }
      ]
    }
  ],
  "entitiesMappings": [
    {
      "name": "UserStoryMapping",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory_Name"
        }
      ]
    },
    {
      "name": "ProjectMapping",
      "tpEntityTypeName": "Project",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "Project_Name"
        }
      ]
    }
  ]
}

엔티티 간 관계 정의(M-M)

다대다 관계는 하나 이상의 엔티티(에지)가 하나 이상의 엔티티(엣지)와 연결될 수 있음을 의미합니다. 이러한 엔티티의 연결은 루트 엔티티를 사용하여 수행됩니다. 이러한 엔티티에는 관계의 어느 에지가 어느 에지에 연결되는지에 대한 정보가 포함되어 있습니다. 예를 들어 User를 UserStory 에 할당하는 간단한 버전을 살펴 보겠습니다. Targetprocess 에서는 여러 사용자 스토리에 여러 사용자를 할당할 수 있으므로 이러한 엔티티가 에지가 됩니다. 이러한 에지를 연결하려면 루트 엔티티(이 경우 할당 )가 필요합니다
{
  "relations": [
    {
      "root": {
        "mappingName": "AssignmentMapping"
      },
      "edges": [
        {
          "field": "Assignable",
          "mappingName": "UserStoryMapping"
        },
        {
          "field": "GeneralUser",
          "mappingName": "UserMapping"
        }
      ]
    }
  ]
}

과제(M-M 및 M-M-M)

과제는 두 가지 방법으로 가져올 수 있습니다. 다대다 및 다대다 매핑을 사용합니다. 더 간단한 것부터 시작하겠습니다.

다대다

한 프로젝트의 사용자 스토리에 사용자를 할당하고 싶다고 가정해 보겠습니다. 이러한 모든 사용자에게는 기본 역할이 할당됩니다. 이를 위해 다음 CSV 파일을 생성합니다:

User.Email UserStory 이름
noadmin@noadmin.com us1
admin@nonexistingemail.com us1
noadmin@noadmin.com us2

다음으로 사용자, UserStory 및 과제에 대한 매핑을 추가해야 합니다. UserStory 필수 필드 Project. 하나의 프로젝트만 운영할 예정이므로 프로젝트 필드에 ConstantReference 을 사용할 수 있습니다. 마지막으로 관계를 추가할 수 있습니다. 어떤 사용자가 어떤 UserStory 할당에 연결되어 있는지에 대한 정보를 포함하는 엔티티입니다. 그래서 매핑을 루트에 넣었습니다. 에지는 UserStory 와 GeneralUser 입니다. 과제 정의를 살펴보면 UserStory 및 GeneralUser 사용자에 대한 두 개의 필드 Assignable이 포함되어 있음을 알 수 있습니다. 관계 정의에서 이러한 필드를 사용해야 합니다.

전체 매핑은 다음과 같습니다:
{
  "relations": [
    {
      "root": {
        "mappingName": "AssignmentMapping"
      },
      "edges": [
        {
          "field": "Assignable",
          "mappingName": "UserStoryMapping"
        },
        {
          "field": "GeneralUser",
          "mappingName": "UserMapping"
        }
      ]
    }
  ],
  "entitiesMappings": [
    {
      "name": "UserStoryMapping",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory.Name"
        },
        {
          "kind": "ConstantReference",
          "constValue": {
            "id": 1008
          },
          "tpFieldName": "Project"
        }
      ]
    },
    {
      "name": "UserMapping",
      "tpEntityTypeName": "User",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Email",
          "csvColumnName": "User.Email"
        }
      ]
    },
    {
      "name": "AssignmentMapping",
      "tpEntityTypeName": "Assignment",
      "fieldsMappings": []
    }
  ] 
}
다대다 다대다

이전 예제에는 몇 가지 제한 사항이 있습니다. 할당된 사용자의 역할을 동적으로 설정할 수 없습니다. 이 제약을 극복하려면 관계에 또 다른 에지를 추가해야 합니다. 세 번째 에지는 Role.Let 의 이전 CSV 파일을 수정하고 사용자 역할을 추가합니다.

User.Email UserStory 이름 Role.Name
noadmin@noadmin.com us1 개발자
admin@nonexistingemail.com us1 QA 엔지니어
noadmin@noadmin.com us2 개발자
다음으로, 역할에 대한 매핑을 추가하고 관계에서 이 엔터티에 대한 에지를 추가해야 합니다. 할당은 필드 역할에 역할과의 관계를 저장합니다. 전체 매핑은 다음과 같습니다:
{
  "relations": [
    {
      "root": {
        "mappingName": "AssignmentMapping"
      },
      "edges": [
        {
          "field": "Assignable",
          "mappingName": "UserStoryMapping"
        },
        {
          "field": "GeneralUser",
          "mappingName": "UserMapping"
        },
        {
          "field": "Role",
          "mappingName": "RoleMapping"
        }
      ]
    }
  ],
  "entitiesMappings": [
    {
      "name": "UserStoryMapping",
      "tpEntityTypeName": "UserStory",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "UserStory.Name"
        },
        {
          "kind": "ConstantReference",
          "constValue": {
            "id": 1008
          },
          "tpFieldName": "Project"
        }
      ]
    },
    {
      "name": "UserMapping",
      "tpEntityTypeName": "User",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Email",
          "csvColumnName": "User.Email"
        }
      ]
    },
    {
      "name": "RoleMapping",
      "tpEntityTypeName": "Role",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "Role.Name"
        }
      ]
    },
    {
      "name": "AssignmentMappingName",
      "tpEntityTypeName": "Assignment",
      "fieldsMappings": []
    }
  ]
}

관계 조회

관계에 대한 조회도 정의할 수 있습니다. 생성하거나 업데이트해야 하는 엔티티는 관련 엔티티의 이름을 기준으로 선택할 수 있습니다.

PeriodBudget, 엔티티의 내부 비용(IT) 필드에 있는 데이터를 업데이트하고 싶지만 첫 번째 열에 나열된 포트폴리오 에픽( PE1,PE2,PE3 ) 및 두 번째 열에 나열된 기간(1월)과 관련된 경우에만 업데이트한다고 가정해 보겠습니다. 이를 위해 다음 CSV 파일을 생성합니다:

PortfolioEpic 이름 Period.Name PeriodBudget InternalCost(IT)
PE1 1월 2023 100년
PE2 1월 2023 2억
Pe3 1월 2023 300
전체 매핑은 다음과 같습니다:
{
  "relations": [
    {
      "root": {
        "mappingName": "PeriodBudgetMappingName"
      },
      "edges": [
        {
          "field": "PortfolioEpic",
          "isLookup": true,
          "mappingName": "PortfolioEpicReferenceMapping"
        },
        {
          "field": "Period",
          "isLookup": true,
          "mappingName": "PeriodReferenceMapping"
        }
      ]
    }
  ],
  "entitiesMappings": [
    {
      "name": "PeriodBudgetMappingName",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "PeriodBudget "
        },
        {
          "tpFieldName": "Internal Cost (IT)",
          "csvColumnName": "InternalCost(IT)"
        },
        {
          "kind": "ConstantReference",
          "constValue": {
            "id": 1234
          },
          "tpFieldName": "Project"
        }
      ],
      "tpEntityTypeName": "PeriodBudget"
    },
    {
      "name": "PortfolioEpicReferenceMapping",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": "PortfolioEpic.Name"
        }
      ],
      "tpEntityTypeName": "PortfolioEpic"
    },
    {
      "name": "PeriodReferenceMapping",
      "fieldsMappings": [
        {
          "isLookup": true,
          "tpFieldName": "Name",
          "csvColumnName": " Period.Name"
        }
      ],
      "tpEntityTypeName": "Period"
    }
  ]
}