Files
monorepo/LCU.API.Operations.IncentiveAPI/LCU.API.Internal.Operations.IncentiveApi/Controllers/ActivityController.cs
T
2026-03-17 09:53:09 -05:00

752 lines
25 KiB
C#

using LCU.API.Internal.Operations.IncentiveApi.Exceptions;
using LCU.API.Internal.Operations.IncentiveApi.Services;
using LCU.API.Internal.Operations.IncentiveApi.Services.AutoDecision;
using LCU.API.Internal.Operations.IncentiveApiLib.Services;
using LCU.API.Internal.Operations.IncentiveApi.Models.DataTransfer;
using LCU.API.Internal.Operations.IncentiveApi.Models;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.FeatureManagement.Mvc;
using LCU.API.Internal.Operations.IncentiveApi.Authorization;
using LCU.API.Internal.Operations.IncentiveApi.Configuration;
using LCU.Library.Internal.IncentiveApiModels.Enums;
using LCU.Library.Internal.IncentiveApiModels.Entities;
using LCU.Library.Internal.IncentiveApiModels.Common;
using LCU.API.Internal.Operations.IncentiveApiLib.Persistence;
namespace LCU.API.Internal.Operations.IncentiveApi.Controllers;
[FeatureGate(FeatureFlags.EnableControllers)]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[ApiController]
[Route("api/[controller]")]
public class ActivityController : ControllerBase
{
private readonly IActivityService _activityService;
private readonly IActivityDetailService _activityDetailService;
private readonly IDashboardService _dashboardService;
private readonly IUserService _userService;
private readonly ICurrentUserService _currentUser;
private readonly IActivityDecisionService _activityDecisionService;
private readonly IEStatementService _eStatementService;
public ActivityController(IActivityService activityService, IActivityDetailService activityDetailService, IUserService userService,
ICurrentUserService currentUser, IDashboardService dashboardService, IActivityDecisionService activityDecisionService,
IEStatementService eStatementService)
{
_activityService = activityService;
_activityDetailService = activityDetailService;
_userService = userService;
_currentUser = currentUser;
_dashboardService = dashboardService;
_activityDecisionService = activityDecisionService;
_eStatementService = eStatementService;
}
[HttpGet("paged")]
[ProducesResponseType(typeof(PagedResponse<Activity>), 200)]
public async Task<IActionResult> Get([FromQuery] ActivityFilter filter)
{
try
{
var searchResult = await _activityService.ListByFilterAsync(filter);
foreach (var activity in searchResult.Items)
{
activity?.TransformForView();
}
var result = new PagedResponse<Activity>(searchResult, filter, Url, Request);
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("me", Name = "GetCurrentUserProgress")]
[RequirePermission("VIEW_DASHBOARD")]
public async Task<IActionResult> GetCurrentUserProgress([FromQuery] int fromMonth, [FromQuery] int fromYear,
[FromQuery] int toMonth, [FromQuery] int toYear, [FromQuery] string employeeId = "")
{
try
{
var monthRange = new MonthRange(fromYear, fromMonth, toYear, toMonth);
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (!string.IsNullOrWhiteSpace(employeeId))
{
employee = await _userService.GetUserByEmployeeIdAsync(employeeId);
}
if (employee == null)
{
return NoContent();
}
var result = await _dashboardService.GetEmployeeProgressForMonthRangeAsync(employee, monthRange);
result?.TransformForView();
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("me/departments", Name = "GetCurrentUserDepartmentProgress")]
[RequirePermission("VIEW_DASHBOARD,VIEW_PERFORMANCE_FOR_DEPARTMENT")]
public async Task<IActionResult> GetCurrentUserDepartmentProgress([FromQuery] int fromMonth,
[FromQuery] int fromYear,
[FromQuery] int toMonth, [FromQuery] int toYear, [FromQuery] int departmentId = 0)
{
try
{
var monthRange = new MonthRange(fromYear, fromMonth, toYear, toMonth);
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (employee == null)
{
return NoContent();
}
var result = new List<DepartmentProgress>();
if (departmentId != 0)
{
result.Add(
await _dashboardService.GetDepartmentProgressForMonthRangeAsync(departmentId, monthRange));
}
else
{
result.AddRange(
await _dashboardService.GetDepartmentProgressForMonthRangeAsync(employee.Departments,
monthRange));
}
foreach (var departmentProgress in result)
{
departmentProgress?.TransformForView();
}
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("region", Name = "GetRegionProgress")]
[RequirePermission("VIEW_DASHBOARD,VIEW_PERFORMANCE_FOR_REGION")]
public async Task<IActionResult> GetRegionProgress([FromQuery] int fromMonth,
[FromQuery] int fromYear,
[FromQuery] int toMonth, [FromQuery] int toYear, [FromQuery] string regionCode)
{
try
{
var monthRange = new MonthRange(fromYear, fromMonth, toYear, toMonth);
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (employee == null)
{
return NoContent();
}
List<Region> regions = new List<Region>();
if (string.IsNullOrEmpty(regionCode))
{
var userDept = employee.Departments.FirstOrDefault(x => x.Role == Role.RegionalManager);
if (userDept == null)
{
return Unauthorized("No User-Dept for region found.");
}
regions.Add(Region.FindByCode(userDept.Department.RegionCode));
}
else if (regionCode == "ALL")
{
regions = Region.Regions;
}
else
{
regions.Add(Region.FindByCode(regionCode));
}
if (!regions.Any())
{
return NoContent();
}
var regionProgress = new List<RegionProgress>();
foreach (var region in regions)
{
var result =
await _dashboardService.GetRegionProgressForMonthRangeAsync(region, monthRange);
regionProgress.Add(result);
}
foreach (var region in regionProgress)
{
region?.TransformForView();
}
return Ok(regionProgress);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("businessLine", Name = "GetBusinessLineProgress")]
[RequirePermission("VIEW_DASHBOARD,VIEW_PERFORMANCE_FOR_BUSINESS_LINE")]
public async Task<IActionResult> GetBusinessLineProgress([FromQuery] int fromMonth,
[FromQuery] int fromYear,
[FromQuery] int toMonth, [FromQuery] int toYear, [FromQuery] string businessLineCode)
{
try
{
var monthRange = new MonthRange(fromYear, fromMonth, toYear, toMonth);
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (employee == null)
{
return NoContent();
}
List<BusinessLine> bls = new List<BusinessLine>();
if (string.IsNullOrEmpty(businessLineCode))
{
var userDept = employee.FindDepartmentForRole(Role.BusinessLineManager);
if (userDept == null)
{
return Unauthorized("No User-Dept for business line found.");
}
bls.Add(BusinessLine.FindByCode(userDept.Department.BusinessLineCode));
}
else if (businessLineCode == "ALL")
{
bls = BusinessLine.BusinessLines;
}
else
{
bls.Add(BusinessLine.FindByCode(businessLineCode));
}
if (!bls.Any())
{
return NoContent();
}
var blProgress = new List<BusinessLineProgress>();
foreach (var bl in bls)
{
var result =
await _dashboardService.GetBusinessLineProgressForMonthRangeAsync(bl, monthRange);
blProgress.Add(result);
}
foreach (var bl in blProgress)
{
bl?.TransformForView();
}
return Ok(blProgress);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost]
public async Task<IActionResult> CreateActivity([FromBody] Activity activity)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _activityService.SaveActivityAsync(activity);
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("StateChange")]
[HttpPost("ManualStateChange")]
public async Task<IActionResult> ManuallyUpdateActivityState([FromBody] ActivityStateChange activityStateChange)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (employee == null)
{
return Unauthorized("No AD User Found.");
}
await _activityService.ValidateCanApplyActivityStateChange(employee, activityStateChange);
var result = await _activityService.ApplyStateChange(activityStateChange);
result?.TransformForView();
return Ok(result);
}
catch (BadActivityStateChangeException ex)
{
return BadRequest(ex.Message);
}
catch (NotAuthorizedException ex)
{
return StatusCode(403, ex.Message);
}
catch (NotFoundException)
{
return BadRequest("Activity Not Found.");
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("{activityId}/StateChanges")]
public async Task<IActionResult> GetActivityStateChanges([FromRoute] int activityId)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _activityService.GetActivityStateChanges(activityId);
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("{activityId:int}/DetailChanges")]
public async Task<IActionResult> GetActivityDetailChanges([FromRoute] int activityId)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var activity = await _activityService.GetActivity(activityId);
var result = await _activityDetailService.GetAllActivityDetailUpdates(activity.Detail.Id);
if (result == null || !result.Any())
{
NoContent();
}
return Ok(result);
}
catch (NotFoundException)
{
return NotFound($"No activity with Id {activityId} could be found");
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("{activityId}/AvailableCommands")]
public async Task<IActionResult> GetActivityAuthorizedCommands([FromRoute] int activityId, [FromQuery] string employeeId)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (!string.IsNullOrWhiteSpace(employeeId))
{
employee = await _userService.GetUserByEmployeeIdAsync(employeeId);
}
if (employee == null)
{
return Unauthorized("No AD User Found.");
}
var result = await _activityService.GetActivityAuthorizedCommands(employee, activityId);
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("{activityId}")]
public async Task<IActionResult> Get([FromRoute] int activityId)
{
try
{
var result = await _activityService.GetActivity(activityId);
result?.TransformForView();
return Ok(result);
}
catch (NotFoundException)
{
return BadRequest("Activity Not Found.");
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("RequestTransfer")]
[RequirePermission("TRANSFER_ACTIVITIES_BETWEEN_DEPARTMENTS, TRANSFER_ACTIVITIES_BETWEEN_ASSOCIATES")]
public async Task<IActionResult> RequestTransfer([FromBody] ActivityTransferRequest transferRequest)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _activityService.RequestTransfer(transferRequest);
result?.TransformForView();
return Ok(result);
}
catch (NotFoundException)
{
return BadRequest("Activity Not Found.");
}
catch (BadActivityTransferActionException ex)
{
return BadRequest(ex.Message);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("RequestTransferToOwnDepartment")]
public async Task<IActionResult> RequestTransferToOwnDepartment([FromBody] ActivityTransferRequest transferRequest)
{
try
{
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (employee == null)
{
return NoContent();
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _activityService.TransferToOwnDepartment(transferRequest, employee);
result?.TransformForView();
return Ok(result);
}
catch (NotFoundException)
{
return BadRequest("Activity Not Found.");
}
catch (BadActivityTransferActionException ex)
{
return BadRequest(ex.Message);
}
catch (NotAuthorizedException ex)
{
return Unauthorized(ex.Message);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost("ApproveTransfer")]
[RequirePermission("TRANSFER_ACTIVITIES_BETWEEN_DEPARTMENTS, TRANSFER_ACTIVITIES_BETWEEN_ASSOCIATES")]
public async Task<IActionResult> ApproveTransfer([FromBody] ActivityTransferApprovalRequest approvalRequest)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var appUser = _currentUser.GetCurrentUser();
if (appUser?.Email == null)
{
return Unauthorized("No AD User Found.");
}
var employee = await _userService.GetUserByAdEmailAsync(appUser.Email);
if (employee == null)
{
return Unauthorized("No AD User Found.");
}
var result = await _activityService.ApproveTransfer(employee, approvalRequest);
result?.TransformForView();
return Ok(result);
}
catch (NotFoundException)
{
return BadRequest("Activity Transfer Not Found.");
}
catch (NotAuthorizedException ex)
{
return StatusCode(403, ex.Message);
}
catch (BadActivityTransferActionException ex)
{
return BadRequest(ex.Message);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("{activityId}/RequestedTransferAction")]
public async Task<IActionResult> GetTransferAction([FromRoute] int activityId)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var result = await _activityService.GetRequestedTransfer(activityId);
result?.TransformForView();
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("")]
[Obsolete("Added here for legacy client support, please use Paginated version")]
public async Task<IActionResult> Get()
{
try
{
var result = await _activityService.GetActivitiesAsync();
foreach (var activity in result)
{
activity?.TransformForView();
}
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("matchActivities")]
[Obsolete("Moved to Processing Controller, please use endpoint QueueNightlyIncentiveProcess/UpdateReferralStatusProcess. Date: 1/1/2025")]
public async Task<IActionResult> GetMatchActivityTemp()
{
try
{
var results = await _activityService.MatchOrExpireReferrals();
return Ok(results);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("updateEStatementReferrals")]
[Obsolete("Moved to Processing Controller, please use endpoint QueueNightlyIncentiveProcess/UpdateEStatementProcess. Date: 1/1/2025")]
public async Task<IActionResult> GetDeliveryMethodsForEStatements()
{
try
{
var results = await _eStatementService.UpdateOrExpireEStatementReferral();
return Ok(results);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("RunDailyManualReviewRequery")]
[Obsolete("Moved to Processing Controller, please use endpoint QueueNightlyIncentiveProcess/UpdateAccountDecisionProcess. Date: 1/1/2025")]
public async Task<IActionResult> RunDailyManualReviewRequery()
{
try
{
var result = await _activityDecisionService.UpdateAndDecideManualReviewActivities();
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("RunDailyLICStationRequery")]
[Obsolete("Moved to Processing Controller, please use endpoint QueueNightlyIncentiveProcess/UpdateLICSalesProcess. Date: 1/1/2025")]
public async Task<IActionResult> RunDailyLICRequery()
{
try
{
var result = await _activityDecisionService.UpdateAndDecideLicReferralActivities();
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("RunDailyDirectDepositRequery")]
[Obsolete("Moved to Processing Controller, please use endpoint QueueNightlyIncentiveProcess/UpdateDirectDepositReferralsProcess. Date: 1/1/2025")]
public async Task<IActionResult> RunDailyDirectDepositRequery()
{
try
{
var result = await _activityDecisionService.UpdateAndDecideDirectDepositPendingReferralActivities();
return Ok(result);
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpGet("RunDecisionService")]
[Obsolete("Moved to Processing Controller, please use endpoint QueueNightlyIncentiveProcess/UpdateAccountDecisionProcess. Date: 1/1/2025")]
public async Task<IActionResult> RunDecisionService()
{
try
{
Log.Information("RunDecisionService was forced");
var decisioned = await _activityDecisionService.DecisionActivityByState(ActivityState.Created);
Log.Information($"Auto-decisioned {decisioned.Count} activities in Created state");
decisioned = await _activityDecisionService.DecisionActivityByState(ActivityState.ManualReview);
Log.Information($"Auto-decisioned {decisioned.Count} activities in Manual Review state");
decisioned = await _activityDecisionService.UpdateAndDecideManualReviewActivities();
Log.Information($"Updated and Auto-Decisioned {decisioned.Count} Activities");
decisioned = await _activityDecisionService.UpdateAndDecideDpEligibleLoanActivities();
Log.Information($"Updated and Auto-Decisioned {decisioned.Count} Debt Protection Eligible Loan Activities");
return Ok();
}
catch (Exception ex)
{
Log.Error(ex, $"Failure in {GetType().Name}.");
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
}