Skip to content

Commit 20bdfda

Browse files
Add ability to get Household Data by Phone for CO
1 parent 5aebaa3 commit 20bdfda

4 files changed

Lines changed: 115 additions & 6 deletions

File tree

src/SEBT.Portal.Api/Composition/Defaults/DefaultSummerEbtCaseService.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,14 @@ internal sealed class DefaultSummerEbtCaseService : ISummerEbtCaseService
2020
{
2121
return Task.FromResult<HouseholdData?>(null);
2222
}
23+
24+
/// <inheritdoc />
25+
public Task<HouseholdData?> GetHouseholdByGuardianPhoneAsync(
26+
string guardianPhone,
27+
PiiVisibility piiVisibility,
28+
IdentityAssuranceLevel identityAssuranceLevel,
29+
CancellationToken cancellationToken = default)
30+
{
31+
return Task.FromResult<HouseholdData?>(null);
32+
}
2333
}

src/SEBT.Portal.Core/AppSettings/StateHouseholdIdSettings.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@ public class StateHouseholdIdSettings
1414
/// Ordered list of household ID types for authorization/linking.
1515
/// The first type that can be resolved from the user is used for lookup.
1616
/// </summary>
17-
public List<PreferredHouseholdIdType> PreferredHouseholdIdTypes { get; set; } = [PreferredHouseholdIdType.Email];
17+
public List<PreferredHouseholdIdType> PreferredHouseholdIdTypes { get; set; } = [];
1818
}

src/SEBT.Portal.Infrastructure/Repositories/HouseholdRepository.cs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,18 @@ public HouseholdRepository(
3434
UserIalLevel userIalLevel,
3535
CancellationToken cancellationToken = default)
3636
{
37-
if (identifier.Type != PreferredHouseholdIdType.Email)
37+
if (identifier.Type == PreferredHouseholdIdType.Email)
3838
{
39-
_logger.LogDebug("State plugin lookup supports only email identifier; ignoring type {Type}", identifier.Type);
40-
return Task.FromResult<HouseholdData?>(null);
39+
return GetHouseholdByEmailAsync(identifier.Value, piiVisibility, userIalLevel, cancellationToken);
4140
}
4241

43-
return GetHouseholdByEmailAsync(identifier.Value, piiVisibility, userIalLevel, cancellationToken);
42+
if (identifier.Type == PreferredHouseholdIdType.Phone)
43+
{
44+
return GetHouseholdByPhoneAsync(identifier.Value, piiVisibility, userIalLevel, cancellationToken);
45+
}
46+
47+
_logger.LogDebug("State plugin lookup does not support identifier type {Type}", identifier.Type);
48+
return Task.FromResult<HouseholdData?>(null);
4449
}
4550

4651
/// <inheritdoc />
@@ -117,6 +122,49 @@ private static HouseholdData ApplyPiiVisibility(HouseholdData source, PiiVisibil
117122
};
118123
}
119124

125+
private async Task<HouseholdData?> GetHouseholdByPhoneAsync(
126+
string phone,
127+
PiiVisibility piiVisibility,
128+
UserIalLevel userIalLevel,
129+
CancellationToken cancellationToken = default)
130+
{
131+
ArgumentNullException.ThrowIfNull(piiVisibility);
132+
if (string.IsNullOrWhiteSpace(phone))
133+
{
134+
return null;
135+
}
136+
137+
_logger.LogDebug("Querying state plugin for household data by guardian phone");
138+
139+
var pluginPii = new PluginPiiVisibility(
140+
piiVisibility.IncludeAddress,
141+
piiVisibility.IncludeEmail,
142+
piiVisibility.IncludePhone);
143+
var pluginIal = (PluginIdentityAssuranceLevel)(int)userIalLevel;
144+
var pluginHousehold = await _summerEbtCaseService.GetHouseholdByGuardianPhoneAsync(
145+
phone,
146+
pluginPii,
147+
pluginIal,
148+
cancellationToken);
149+
150+
if (pluginHousehold == null)
151+
{
152+
_logger.LogInformation("No household data found for guardian phone");
153+
return null;
154+
}
155+
156+
_logger.LogInformation(
157+
"Retrieved household data for guardian by phone with {ApplicationCount} application(s)",
158+
pluginHousehold.Applications.Count);
159+
160+
var core = PluginHouseholdDataMapper.ToCore(pluginHousehold);
161+
if (core == null)
162+
{
163+
return null;
164+
}
165+
return ApplyPiiVisibility(core, piiVisibility);
166+
}
167+
120168
/// <inheritdoc />
121169
public Task UpsertHouseholdAsync(HouseholdData householdData, CancellationToken cancellationToken = default)
122170
{

test/SEBT.Portal.Tests/Unit/Repositories/HouseholdRepositoryTests.cs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,14 +217,65 @@ await _summerEbtCaseService.Received(1)
217217
}
218218

219219
[Fact]
220-
public async Task GetHouseholdByIdentifierAsync_WhenNonEmailIdentifier_ReturnsNullWithoutCallingPlugin()
220+
public async Task GetHouseholdByIdentifierAsync_WhenPhoneIdentifier_DelegatesToPlugin()
221+
{
222+
var phone = "555-123-4567";
223+
var pluginData = new PluginHouseholdData
224+
{
225+
Email = "guardian@example.com",
226+
Phone = phone,
227+
BenefitIssuanceType = PluginBenefitIssuanceType.SummerEbt,
228+
Applications = new List<PluginApplication>()
229+
};
230+
_summerEbtCaseService
231+
.GetHouseholdByGuardianPhoneAsync(phone, Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>())
232+
.Returns(pluginData);
233+
234+
var result = await _repository.GetHouseholdByIdentifierAsync(
235+
HouseholdIdentifier.Phone(phone), FullPii, UserIalLevel.IAL1plus);
236+
237+
Assert.NotNull(result);
238+
await _summerEbtCaseService.Received(1)
239+
.GetHouseholdByGuardianPhoneAsync(phone, Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>());
240+
await _summerEbtCaseService.DidNotReceive()
241+
.GetHouseholdByGuardianEmailAsync(Arg.Any<string>(), Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>());
242+
}
243+
244+
[Fact]
245+
public async Task GetHouseholdByIdentifierAsync_WhenPhoneIdentifierAndPluginReturnsNull_ReturnsNull()
246+
{
247+
_summerEbtCaseService
248+
.GetHouseholdByGuardianPhoneAsync(Arg.Any<string>(), Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>())
249+
.Returns((PluginHouseholdData?)null);
250+
251+
var result = await _repository.GetHouseholdByIdentifierAsync(
252+
HouseholdIdentifier.Phone("555-000-0000"), FullPii, UserIalLevel.IAL1plus);
253+
254+
Assert.Null(result);
255+
}
256+
257+
[Fact]
258+
public async Task GetHouseholdByIdentifierAsync_WhenPhoneIdentifierIsWhitespace_ReturnsNull()
259+
{
260+
var result = await _repository.GetHouseholdByIdentifierAsync(
261+
HouseholdIdentifier.Phone(" "), FullPii, UserIalLevel.IAL1plus);
262+
263+
Assert.Null(result);
264+
await _summerEbtCaseService.DidNotReceive()
265+
.GetHouseholdByGuardianPhoneAsync(Arg.Any<string>(), Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>());
266+
}
267+
268+
[Fact]
269+
public async Task GetHouseholdByIdentifierAsync_WhenNonEmailNonPhoneIdentifier_ReturnsNullWithoutCallingPlugin()
221270
{
222271
var result = await _repository.GetHouseholdByIdentifierAsync(
223272
HouseholdIdentifier.SnapId("SNAP123"), FullPii, UserIalLevel.IAL1plus);
224273

225274
Assert.Null(result);
226275
await _summerEbtCaseService.DidNotReceive()
227276
.GetHouseholdByGuardianEmailAsync(Arg.Any<string>(), Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>());
277+
await _summerEbtCaseService.DidNotReceive()
278+
.GetHouseholdByGuardianPhoneAsync(Arg.Any<string>(), Arg.Any<PluginPiiVisibility>(), Arg.Any<PluginIdentityAssuranceLevel>(), Arg.Any<CancellationToken>());
228279
}
229280

230281
[Fact]

0 commit comments

Comments
 (0)