Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Build, including financial chart details from Aggie Enterprise.

| Method | Route | Authentication | Response |
| --- | --- | --- | --- |
| `GET` | `/api/health` | None | `{"status":"healthy","service":"KOI","version":"0.1.3","revision":"<git-sha-or-local>"}` |
| `GET` | `/api/health` | None | `{"status":"healthy","service":"KOI","version":"0.1.4","revision":"<git-sha-or-local>"}` |
| `GET` | `/api/v1/hello` | Bearer token | `{"message":"Hello from KOI"}` |
| `GET` | `/api/v1/financial/details/{value}` | Bearer token | Flattened financial details for one chart string |

Expand All @@ -18,6 +18,12 @@ Valid GL and PPM results return
`This is a valid GL chart string.` and `This is a valid PPM chart string.`,
respectively. Invalid results return `This is not a valid chart string.`

Segment display names are sourced from the Aggie Enterprise segment details.
GL responses populate `entityName`, `fundName`, `departmentName`, `accountName`,
`purposeName`, `programName`, `projectName`, and `activityName`. PPM responses
populate `projectName`, `taskName`, `expenditureOrganizationName`, and
`expenditureTypeName`. Segment-name fields that do not apply are empty strings.

All HTTP functions require authentication by default. The health function is
the only explicit anonymous exception.

Expand Down
2 changes: 1 addition & 1 deletion scripts/smoke-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ health_status="$(request "$health_file" "$base_url/api/health")"
assert_response \
"Anonymous health" \
200 \
'{"status":"healthy","service":"KOI","version":"0.1.3","revision":"local"}' \
'{"status":"healthy","service":"KOI","version":"0.1.4","revision":"local"}' \
"$health_status" \
"$health_file"

Expand Down
46 changes: 46 additions & 0 deletions src/Koi.Functions/Financial/Models/FinancialDetails.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ namespace Koi.Functions.Financial.Models;

public sealed class FinancialDetails
{
private const string EntitySegment = "Entity";
private const string FundSegment = "Fund";
private const string DepartmentSegment = "Department";
private const string AccountSegment = "Account";
private const string PurposeSegment = "Purpose";
private const string ProgramSegment = "Program";
private const string ProjectSegment = "Project";
private const string ActivitySegment = "Activity";
private const string TaskSegment = "Task";
private const string ExpenditureOrganizationSegment = "Expenditure Organization";
private const string ExpenditureTypeSegment = "Expenditure Type";
private const string GlFinancialDepartmentEntity = "GL Financial Department";
private const string AwardEntity = "Award";
private const string PrincipalInvestigatorRole = "Principal Investigator";
Expand All @@ -20,6 +31,28 @@ public sealed class FinancialDetails

public string Warning { get; set; } = string.Empty;

public string EntityName { get; set; } = string.Empty;

public string FundName { get; set; } = string.Empty;

public string DepartmentName { get; set; } = string.Empty;

public string AccountName { get; set; } = string.Empty;

public string PurposeName { get; set; } = string.Empty;

public string ProgramName { get; set; } = string.Empty;

public string ProjectName { get; set; } = string.Empty;

public string ActivityName { get; set; } = string.Empty;

public string TaskName { get; set; } = string.Empty;

public string ExpenditureOrganizationName { get; set; } = string.Empty;

public string ExpenditureTypeName { get; set; } = string.Empty;

public string GlFinancialDepartmentName { get; set; } = string.Empty;

public string ProjectStartDate { get; set; } = string.Empty;
Expand Down Expand Up @@ -63,6 +96,19 @@ public static FinancialDetails FromAeDetails(AeDetails aeDetails)
ChartString = aeDetails.ChartString,
Error = aeDetails.Error,
Warning = aeDetails.Warning,
EntityName = FindSegmentName(aeDetails, EntitySegment),
FundName = FindSegmentName(aeDetails, FundSegment),
DepartmentName = FindSegmentName(aeDetails, DepartmentSegment),
AccountName = FindSegmentName(aeDetails, AccountSegment),
PurposeName = FindSegmentName(aeDetails, PurposeSegment),
ProgramName = FindSegmentName(aeDetails, ProgramSegment),
ProjectName = FindSegmentName(aeDetails, ProjectSegment),
ActivityName = FindSegmentName(aeDetails, ActivitySegment),
TaskName = FindSegmentName(aeDetails, TaskSegment),
ExpenditureOrganizationName = FindSegmentName(
aeDetails,
ExpenditureOrganizationSegment),
ExpenditureTypeName = FindSegmentName(aeDetails, ExpenditureTypeSegment),
GlFinancialDepartmentName = FindSegmentName(
aeDetails,
GlFinancialDepartmentEntity),
Expand Down
2 changes: 1 addition & 1 deletion src/Koi.Functions/Koi.Functions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>Koi.Functions</RootNamespace>
<Version>0.1.3</Version>
<Version>0.1.4</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
46 changes: 46 additions & 0 deletions tests/Koi.Functions.Tests/Financial/FinancialFunctionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,26 @@ public async Task RunReturnsOnlyFlatMappedFinancialDetails()
Entity = "Award",
Code = "A232815",
Name = "A232815 SP0A232815 PO2610129 Electrochemically Mediated Air Separation Modules (EM-ASM)"
},
new SegmentDetails
{
Entity = "Project",
Name = "Air Separation Project"
},
new SegmentDetails
{
Entity = "Task",
Name = "Prototype Development"
},
new SegmentDetails
{
Entity = "Expenditure Organization",
Name = "Chemical Engineering"
},
new SegmentDetails
{
Entity = "Expenditure Type",
Name = "Research Supplies"
}
],
Approvers =
Expand Down Expand Up @@ -156,6 +176,17 @@ public async Task RunReturnsOnlyFlatMappedFinancialDetails()
"error",
"warning",
"glFinancialDepartmentName",
"entityName",
"fundName",
"departmentName",
"accountName",
"purposeName",
"programName",
"projectName",
"activityName",
"taskName",
"expenditureOrganizationName",
"expenditureTypeName",
"projectStartDate",
"projectCompletionDate",
"awardStatus",
Expand Down Expand Up @@ -188,6 +219,21 @@ public async Task RunReturnsOnlyFlatMappedFinancialDetails()
Assert.Equal(
"Biological Sciences",
root.GetProperty("glFinancialDepartmentName").GetString());
Assert.Equal(string.Empty, root.GetProperty("entityName").GetString());
Assert.Equal(string.Empty, root.GetProperty("fundName").GetString());
Assert.Equal(string.Empty, root.GetProperty("departmentName").GetString());
Assert.Equal(string.Empty, root.GetProperty("accountName").GetString());
Assert.Equal(string.Empty, root.GetProperty("purposeName").GetString());
Assert.Equal(string.Empty, root.GetProperty("programName").GetString());
Assert.Equal("Air Separation Project", root.GetProperty("projectName").GetString());
Assert.Equal(string.Empty, root.GetProperty("activityName").GetString());
Assert.Equal("Prototype Development", root.GetProperty("taskName").GetString());
Assert.Equal(
"Chemical Engineering",
root.GetProperty("expenditureOrganizationName").GetString());
Assert.Equal(
"Research Supplies",
root.GetProperty("expenditureTypeName").GetString());
Assert.Equal("2025-01-01", root.GetProperty("projectStartDate").GetString());
Assert.Equal("2026-12-31", root.GetProperty("projectCompletionDate").GetString());
Assert.Equal("Active", root.GetProperty("awardStatus").GetString());
Expand Down
81 changes: 80 additions & 1 deletion tests/Koi.Functions.Tests/ResponseContractTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void HealthContractIsStable()

Assert.Equal("healthy", response.Status);
Assert.Equal("KOI", response.Service);
Assert.Equal("0.1.3", response.Version);
Assert.Equal("0.1.4", response.Version);
Assert.NotEmpty(response.Revision);
}

Expand Down Expand Up @@ -67,6 +67,17 @@ public void FinancialDetailsMapsMissingOptionalValuesToEmptyStrings()
Assert.Equal("invalid", response.ChartString);
Assert.Equal("Invalid Chart Type", response.Error);
Assert.Equal("Example warning", response.Warning);
Assert.Equal(string.Empty, response.EntityName);
Assert.Equal(string.Empty, response.FundName);
Assert.Equal(string.Empty, response.DepartmentName);
Assert.Equal(string.Empty, response.AccountName);
Assert.Equal(string.Empty, response.PurposeName);
Assert.Equal(string.Empty, response.ProgramName);
Assert.Equal(string.Empty, response.ProjectName);
Assert.Equal(string.Empty, response.ActivityName);
Assert.Equal(string.Empty, response.TaskName);
Assert.Equal(string.Empty, response.ExpenditureOrganizationName);
Assert.Equal(string.Empty, response.ExpenditureTypeName);
Assert.Equal(string.Empty, response.GlFinancialDepartmentName);
Assert.Equal(string.Empty, response.ProjectStartDate);
Assert.Equal(string.Empty, response.ProjectCompletionDate);
Expand All @@ -82,6 +93,74 @@ public void FinancialDetailsMapsMissingOptionalValuesToEmptyStrings()
Assert.Equal(string.Empty, response.FundPurpose);
}

[Fact]
public void FinancialDetailsMapsGlSegmentNamesFromAeDetails()
{
var response = FinancialDetails.FromAeDetails(new AeDetails
{
ChartStringType = FinancialChartStringType.Gl,
SegmentDetails =
[
new SegmentDetails { Entity = "Entity", Name = "UC Davis" },
new SegmentDetails { Entity = "Fund", Name = "General Funds" },
new SegmentDetails { Entity = "Department", Name = "Computer Science" },
new SegmentDetails { Entity = "Account", Name = "Supplies" },
new SegmentDetails { Entity = "Purpose", Name = "Instruction" },
new SegmentDetails { Entity = "Program", Name = "Academic Programs" },
new SegmentDetails { Entity = "Project", Name = "Campus Project" },
new SegmentDetails { Entity = "Activity", Name = "Core Activity" }
]
});

Assert.Equal("UC Davis", response.EntityName);
Assert.Equal("General Funds", response.FundName);
Assert.Equal("Computer Science", response.DepartmentName);
Assert.Equal("Supplies", response.AccountName);
Assert.Equal("Instruction", response.PurposeName);
Assert.Equal("Academic Programs", response.ProgramName);
Assert.Equal("Campus Project", response.ProjectName);
Assert.Equal("Core Activity", response.ActivityName);
Assert.Equal(string.Empty, response.TaskName);
Assert.Equal(string.Empty, response.ExpenditureOrganizationName);
Assert.Equal(string.Empty, response.ExpenditureTypeName);
}

[Fact]
public void FinancialDetailsMapsPpmSegmentNamesFromAeDetails()
{
var response = FinancialDetails.FromAeDetails(new AeDetails
{
ChartStringType = FinancialChartStringType.Ppm,
SegmentDetails =
[
new SegmentDetails { Entity = "Project", Name = "Research Project" },
new SegmentDetails { Entity = "Task", Name = "Project Task" },
new SegmentDetails
{
Entity = "Expenditure Organization",
Name = "Engineering"
},
new SegmentDetails
{
Entity = "Expenditure Type",
Name = "Research Supplies"
}
]
});

Assert.Equal("Research Project", response.ProjectName);
Assert.Equal("Project Task", response.TaskName);
Assert.Equal("Engineering", response.ExpenditureOrganizationName);
Assert.Equal("Research Supplies", response.ExpenditureTypeName);
Assert.Equal(string.Empty, response.EntityName);
Assert.Equal(string.Empty, response.FundName);
Assert.Equal(string.Empty, response.DepartmentName);
Assert.Equal(string.Empty, response.AccountName);
Assert.Equal(string.Empty, response.PurposeName);
Assert.Equal(string.Empty, response.ProgramName);
Assert.Equal(string.Empty, response.ActivityName);
}

[Theory]
[InlineData(
true,
Expand Down