---
title: Personnel Information Data Block
description: "The **Personnel Information (**PersonnelInformation**) Data Block** in Assette retrieves active personnel details as of a specified date. It allows users to apply filters such as gender, job function, management status, investment professional status, ethnicity, and founder status. This block consolidates…"
url: "https://learn.assette.com/docs/personnel-information-data-block/"
updated: "2025-09-02"
category: Developers / Data Blocks / Data Blocks by Functionality / Qualitative Information
---

# Personnel Information Data Block

The **Personnel Information (**PersonnelInformation**) Data Block** in Assette retrieves active personnel details as of a specified date. It allows users to apply filters such as gender, job function, management status, investment professional status, ethnicity, and founder status. This block consolidates personnel metadata and experience calculations, returning enriched personnel profiles with structured details on job roles, tenure, experience, and organizational attributes.

### General Info

| Field | Value |
| --- | --- |
| Name | PersonnelInformation |
| Block Category | Interface |
| Block Type | Python |
| Output Type | Data Table |
| Editable | False |
| Public Block | True |

### Definition

```
PeopleMetadata = read("qualitativeMetadata",{"type": "People"})["data"]

field_title_dict = {}

for pdict in PeopleMetadata["fields"]:
    field_title_dict[pdict["name"]] = pdict["title"]

fields = list(field_title_dict.keys())

if "fields" in params and params["fields"]:
    # templist = params["fields"].split('|')
    templist = params["fields"].replace('|', ',').split(',')
    for item in templist:
        if item not in fields:
            fields.append(item)

fields = "|".join(fields)

data = read("GetPersonnelInfo",{"fields": fields,"getdataasofnow": params["getdataasofnow"],"asofdate": params["AsofDate"]})["data"]

df = pd.DataFrame(data)
as_of_date = pd.to_datetime(params["AsofDate"], errors="coerce")
getdataasofnow = params["getdataasofnow"]
if (isinstance(getdataasofnow, str) and getdataasofnow.lower() == "yes") or getdataasofnow is True:
    current_date = datetime.datetime.now()
    as_of_date = pd.to_datetime(current_date, errors="coerce")

def convert_days_to_ymd(days):
    start_date = datetime(1, 1, 1)
    end_date = start_date + timedelta(days=int(days))
    years = end_date.year - start_date.year
    months = end_date.month - start_date.month
    days = end_date.day - start_date.day
    if days < 0:
        months -= 1
        days += (start_date + timedelta(days=30)).day
    if months < 0:
        years -= 1
        months += 12
    return f"{years} Year(s) {months} Month(s) and {days} Day(s)"

# Check if the DataFrame is not empty before applying conditions
if not df.empty:
    # Filter the DataFrame based on the conditions
    df = df[
        ((df['firmStartDate'].isna() | (pd.to_datetime(df['firmStartDate'], errors='coerce', format='%m/%d/%Y') < as_of_date)) &
        ((df['terminationDate'].isna()) | (pd.to_datetime(df['terminationDate'], errors='coerce', format='%m/%d/%Y') > as_of_date) | ('isEmployeeStillAtCompany' in df.columns and df['isEmployeeStillAtCompany'] == 'Yes')))
    ]

    columns_to_convert = [
    "totalExperience",
    "totalIndustryExperience",
    "totalInvestmentExperience",
    "totalProfessionalExperience",
    "totalExperienceAtCurrentOrganization",
    "continuousExperienceAtCurrentOrganization",
    "previousStintsAtCurrentOrganization"
    ]

    for column in columns_to_convert:
        if column in df.columns:
            # df[column] = df[column].apply(lambda days: (lambda start_date, end_date: f"{end_date.year - start_date.year - ((end_date.month, end_date.day) < (start_date.month, start_date.day))} Year(s) {((end_date.month - start_date.month - (end_date.day < start_date.day)) % 12)} Month(s) and {(end_date - (start_date + timedelta(days=(end_date - start_date).days // 365 * 365 + (end_date - start_date).days % 365 // 30 * 30))).days} Day(s)")(
            #     datetime(1, 1, 1), datetime(1, 1, 1) + datetime.timedelta(days=int(days))
            # ))
            # df[column] = df[column].apply(convert_days_to_ymd)
            # df[column] = df[column].apply(convert_days_to_years_months_days)
            df[column] = df[column].apply(lambda days: f"{int(days) // 365} Year(s) {(int(days) % 365) // 30} Month(s) and {(int(days) % 365) % 30} Day(s)")

else:
    # If DataFrame is empty, create an empty DataFrame with the same columns
    df = pd.DataFrame(columns=df.columns)

def filter_row(row, params):
    # Check if the row matches all specified criteria
    return (
        (params["gender"] == "All" or ('gender' in row and row["gender"] == params["gender"]))
        and (params["investmentProfessional"] == "All" or ('investmentProfessional' in row and row["investmentProfessional"] == params["investmentProfessional"]))
        and (params["management"] == "All" or ('management' in row and row["management"] == params["management"]))
        and (params["ethnicity"] == "All" or ('ethnicity' in row and str(row["ethnicity"]) in params["ethnicity"] and str(row["ethnicity"]) != ""))
        and (params["isTheEmployeeAFounderOfTheOrganization"] == "All" or ('isTheEmployeeAFounderOfTheOrganization' in row and row["isTheEmployeeAFounderOfTheOrganization"] == params["isTheEmployeeAFounderOfTheOrganization"]))
        and (params["primaryJobFunction"] == "All" or
            ('primaryJobFunction' in row and str(row["primaryJobFunction"]) in params["primaryJobFunction"] and str(row["primaryJobFunction"]) != ""))
    )

# Apply the filter function to the DataFrame and store the result in a new DataFrame
filtered_df = df[df.apply(filter_row, axis=1, params=params)]

# Reset the index of the filtered DataFrame
filtered_df.reset_index(drop=True, inplace=True)

final_result_list = []
for i in range(filtered_df.shape[0]):
    row_dict = filtered_df.loc[i].to_dict()
    flat_row = {}
    for k, v in row_dict.items():
        # Flatten dict
        if isinstance(v, dict):
            flat_row[k] = ', '.join([str(key) + ': ' + str(value) for key, value in v.items()])
        # Flatten list of dicts
        elif isinstance(v, list) and all(isinstance(item, dict) for item in v):
            flat_row[k] = ' | '.join([', '.join([str(key) + ': ' + str(value) for key, value in item.items()]) for item in v])
        # Flatten list of other types
        elif isinstance(v, list):
            flat_row[k] = ', '.join([str(item) for item in v])
        else:
            flat_row[k] = "" if v is None else str(v)
    final_result_list.append(flat_row)

response["data"]=final_result_list
response["values"]=field_title_dict
```

### Columns

| Column Name | Required | Description |
| --- | --- | --- |
| PersonnelId | Yes | Unique identifier for the personnel |
| firstName | Yes | First name of the individual |
| lastName | Yes | Last name of the individual |
| preferredFirstName | No | Preferred first name |
| preferredFullName | No | Preferred full name (first + last) |
| prefix | No | Prefix such as Mr., Ms., Dr. |
| middleInitial | No | Middle initial |
| suffix | No | Name suffix (e.g., Jr., Sr.) |
| gender | No | Gender of the individual |
| dateOfBirth | No | Date of birth |
| nationality | No | Nationality of the individual |
| ethnicity | No | Ethnicity of the individual |
| isMinority | No | Whether the individual is identified as a minority |
| veteranStatus | No | Veteran status |
| isEmployeeDisabled | No | Disability status |
| phone | No | Primary phone number |
| phoneSecondary | No | Secondary phone number |
| phoneTertiary | No | Tertiary phone number |
| faxNumber | No | Primary fax number |
| faxNumberSecondary | No | Secondary fax number |
| email | No | Primary email address |
| secondaryEmail | No | Secondary email address |
| profileImage | No | Reference to personnel’s profile image |
| signatureImage | No | Reference to personnel’s signature image |
| firmStartDate | No | Date the person joined the firm |
| terminationDate | No | Termination date if applicable |
| isEmployeeStillAtCompany | No | Whether the person is still at the company |
| isDepartureVoluntary | No | Whether the departure was voluntary |
| reasonForDeparture | No | Reason for leaving the firm |
| jobTitle | No | Current job title |
| jobGrade | No | Job grade or seniority level |
| jobRank | No | Rank associated with the job |
| jobCategory | No | Job category (e.g., Professional) |
| jobStatus | No | Status (Employee, Contractor, etc.) |
| jobFunction | No | Functional role |
| primaryJobFunction | No | Primary job function |
| secondaryJobFunctions | No | Secondary job functions |
| previousPrimaryJobFunctions | No | Previously held primary job functions |
| previousSecondaryJobFunctions | No | Previously held secondary job functions |
| priorPrimaryJobFunctions | No | Prior job functions at the organization |
| priorExperiences | No | Prior professional experience details |
| management | No | Whether part of management |
| managementLevel | No | Management level classification |
| investmentProfessional | No | Whether an investment professional |
| partnerAtFirm | No | Whether the person is a partner at the firm |
| isTheEmployeeAFounderOfTheOrganization | No | Whether the individual is a founder |
| commitment | No | Work commitment (Full-Time, Part-Time) |
| assetClassCoverage | No | Asset classes covered |
| secondaryAssetClassCoverage | No | Secondary asset class coverage |
| sectorCoverage | No | Sector coverage |
| industryCoverage | No | Industry coverage |
| regionCoverage | No | Region coverage |
| countryCoverage | No | Country coverage |
| coverageSectionName | No | Coverage section |
| affiliatedOffice | No | Affiliated office location |
| primarySupervisor | No | Supervisor information |
| committees | No | Committees the person is part of |
| degrees | No | Degrees obtained |
| credentials | No | Professional credentials |
| licenses | No | Professional licenses |
| legalIssues | No | Legal issues associated with the individual |
| hasLegalIssues | No | Indicates if the individual has legal issues |
| summaryBio | No | Summary biography |
| detailedBio | No | Detailed biography |
| relevantExperience | No | Notable relevant experience |
| descriptionAboutESGExperience | No | Details on ESG experience |
| hasRelevantESGExperience | No | Indicates if the person has ESG experience |
| doesPersonOwnSharesOfCompany | No | Whether the person owns shares in the company |
| showPersonInBios | No | Whether the person appears in company bios |
| totalExperience | No | Total experience duration |
| totalIndustryExperience | No | Industry experience duration |
| totalInvestmentExperience | No | Investment experience duration |
| totalProfessionalExperience | No | Professional experience duration |
| totalExperienceAtCurrentOrganization | No | Total tenure at current organization |
| continuousExperienceAtCurrentOrganization | No | Continuous tenure at the current organization |
| previousStintsAtCurrentOrganization | No | Number and duration of prior stints at the organization |
| startDate | No | Employment start date (formatted) |
| code | No | Internal personnel code identifier |

### Request Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| gender | Text | Filter by gender or “All” |
| primaryJobFunction | Text | Filter by job function or “All” |
| investmentProfessional | Text | Filter by investment professional flag or “All” |
| management | Text | Filter by management flag or “All” |
| ethnicity | Text | Filter by ethnicity or “All” |
| isTheEmployeeAFounderOfTheOrganization | Text | Filter by founder status or “All” |
| getdataasofnow | Yes/No | If “Yes,” override `AsofDate` with current date |
| AsofDate | Date | Effective date for personnel snapshot |

### Dependencies

| Dependent Block | Description |
| --- | --- |
| GetPersonnelInfo | Retrieves core personnel information used for enrichment and filtering. |
| qualitativeMetadata | Provides metadata definitions for personnel fields (names, titles, mappings). |
| Calculation_Python_Env | Supplies the Python calculation environment required for transformations and experience calculations. |

### Example Request

```
{
"gender":"All",
"primaryJobFunction":"All",
"investmentProfessional":"All",
"management":"All",
"ethnicity":"All",
"isTheEmployeeAFounderOfTheOrganization":"All",
"getdataasofnow":false,
"AsofDate":"12-31-2024"
}
```

### Example Response

*The following code shows an example response using the default values of the Data Block. The response has been shortened for brevity.*

```
{
  "data": [
    {
      "PersonnelId": "7dc017ae-27b2-4a3c-b7c8-fde7b6aafdb7",
      "code": "1113",
      "prefix": "Mr.",
      "firstName": "Jimmy",
      "lastName": "Kennedy",
      "preferredFullName": "Jimmy Kennedy",
      "gender": "Male",
      "ethnicity": "White",
      "isEmployeeStillAtCompany": "Yes",
      "firmStartDate": "12/20/2016",
      "jobTitle": "Portfolio Director",
      "jobGrade": "Managing Director",
      "primaryJobFunction": "Portfolio Management",
      "investmentProfessional": "Yes",
      "management": "Yes",
      "jobStatus": "Employee",
      "totalIndustryExperience": "8 Year(s) 8 Month(s) and 18 Day(s)",
      "totalExperienceAtCurrentOrganization": "8 Year(s) 8 Month(s) and 18 Day(s)",
      "summaryBio": "<p>expertise with experience</p>"
    }
  ],
  "values": {
    "PersonnelId": "PersonnelId",
    "firstName": "First Name",
    "lastName": "Last Name"
  }
}
```
