private static void ValidateReclaim(CarePackageReclaimCreationDomain requestedReclaim, CarePackage package) { var coreCost = package.Details .FirstOrDefault(d => d.Type is PackageDetailType.CoreCost) .EnsureExists($"Core cost for package {package.Id} not found", HttpStatusCode.InternalServerError); if (package.Status.In(PackageStatus.Cancelled, PackageStatus.Ended)) { throw new ApiException($"Can not create FNC reclaim for care package status {package.Status.GetDisplayName()}", HttpStatusCode.BadRequest); } if (package.PackageType != PackageType.NursingCare) { throw new ApiException($"FNC only allowed for nursing care package. Package {package.Id} is invalid", HttpStatusCode.BadRequest); } if (package.Reclaims.Any(r => r.Type is ReclaimType.Fnc)) { throw new ApiException($"FNC already added to package {package.Id}", HttpStatusCode.Conflict); } if (!requestedReclaim.StartDate.IsInRange(coreCost.StartDate, coreCost.EndDate ?? DateTimeOffset.UtcNow.AddYears(10))) { throw new ApiException($"FNC start date must be equal or greater than {coreCost.StartDate}", HttpStatusCode.UnprocessableEntity); } if (requestedReclaim.EndDate != null) { var fncEndDate = (DateTimeOffset)requestedReclaim.EndDate; if (coreCost.EndDate != null && !fncEndDate.IsInRange(coreCost.StartDate, (DateTimeOffset)coreCost.EndDate)) { throw new ApiException($"FNC end date is invalid. Must be in the range {coreCost.StartDate} - {coreCost.EndDate}", HttpStatusCode.UnprocessableEntity); } } }
private static CarePackageReclaim CreateReclaimEntity(CarePackageReclaimCreationDomain requestedReclaim, ReclaimSubType subType) { var fncPayment = requestedReclaim.ToEntity(); fncPayment.Type = ReclaimType.Fnc; fncPayment.SubType = subType; fncPayment.Status = ReclaimStatus.Active; fncPayment.Subjective = fncPayment.SubType == ReclaimSubType.FncPayment ? SubjectiveConstants.FncPaymentSubjectiveCode : SubjectiveConstants.FncReclaimSubjectiveCode; return(fncPayment); }
private static void ValidateProvisionalCareChargeAsync(CarePackageReclaimCreationDomain reclaimCreationDomain, CarePackage carePackage, CarePackageDetail coreCostDetail) { var validReclaimStatuses = new[] { ReclaimStatus.Active, ReclaimStatus.Pending, ReclaimStatus.Ended }; if (reclaimCreationDomain.SubType != ReclaimSubType.CareChargeProvisional) { throw new ApiException($"Cannot create {reclaimCreationDomain.SubType.GetDisplayName()}. Manage other care charges types in the Care Charges menu", HttpStatusCode.BadRequest); } if (carePackage.Reclaims.Any(cc => cc.Type == ReclaimType.CareCharge && cc.SubType == ReclaimSubType.CareChargeProvisional && cc.Status.In(validReclaimStatuses))) { throw new ApiException($"Provisional Care charge assessment for this package already done", HttpStatusCode.BadRequest); } if (carePackage.Reclaims.Any(cc => cc.Type == ReclaimType.CareCharge && cc.SubType != ReclaimSubType.CareChargeProvisional)) { throw new ApiException($"Care charge assessment for this package already done. Manage care charges for this package in the Care Charges menu", HttpStatusCode.BadRequest); } // Start date of provisional CC cannot be before package start date if (!reclaimCreationDomain.StartDate.IsInRange(coreCostDetail.StartDate, coreCostDetail.EndDate ?? DateTimeOffset.UtcNow.AddYears(10))) { throw new ApiException($"{ReclaimSubType.CareChargeProvisional.GetDisplayName()} start date must be equal or greater than {coreCostDetail.StartDate.Date}", HttpStatusCode.UnprocessableEntity); } // End date of provisional CC cannot be before package end date if (reclaimCreationDomain.EndDate != null) { var provisionalCareChargeEndDate = (DateTimeOffset)reclaimCreationDomain.EndDate; if (coreCostDetail.EndDate != null && !provisionalCareChargeEndDate.IsInRange(coreCostDetail.StartDate, (DateTimeOffset)coreCostDetail.EndDate)) { throw new ApiException( $"{reclaimCreationDomain.SubType} end date is invalid. Must be in the range {coreCostDetail.StartDate} - {coreCostDetail.EndDate}", HttpStatusCode.UnprocessableEntity); } } // If provisional cc is set to be ongoing, force end date to be the end date of the package if (coreCostDetail.EndDate != null && reclaimCreationDomain.EndDate == null) { reclaimCreationDomain.EndDate = coreCostDetail.EndDate; } }
public async Task <CarePackageReclaimResponse> CreateProvisionalCareCharge(CarePackageReclaimCreationDomain reclaimCreationDomain, ReclaimType reclaimType) { var carePackage = await _carePackageGateway .GetPackageAsync(reclaimCreationDomain.CarePackageId, PackageFields.Details | PackageFields.Reclaims, true) .EnsureExistsAsync($"Care package with id {reclaimCreationDomain.CarePackageId} not found"); if (carePackage.Status.In(PackageStatus.Cancelled, PackageStatus.Ended)) { throw new ApiException($"Can not create {reclaimType.GetDisplayName()} for care package status {carePackage.Status.GetDisplayName()}", HttpStatusCode.BadRequest); } var coreCostDetail = carePackage.Details .FirstOrDefault(d => d.Type is PackageDetailType.CoreCost) .EnsureExists($"Core cost for package with id {reclaimCreationDomain.CarePackageId} not found", HttpStatusCode.InternalServerError); ValidateProvisionalCareChargeAsync(reclaimCreationDomain, carePackage, coreCostDetail); //todo FK: ? reclaimCreationDomain.SubType = ReclaimSubType.CareChargeProvisional; var newReclaim = reclaimCreationDomain.ToEntity(); //todo FK: ? newReclaim.Type = ReclaimType.CareCharge; newReclaim.Status = ReclaimStatus.Active; newReclaim.Subjective = SubjectiveConstants.CareChargeReclaimSubjectiveCode; carePackage.Reclaims.Add(newReclaim); carePackage.Histories.Add(new CarePackageHistory { Description = $"{reclaimType.GetDisplayName()} {reclaimCreationDomain.SubType.GetDisplayName()} Created", }); // Change status of package to submitted for approval if (carePackage.Status == PackageStatus.Approved) { carePackage.Status = PackageStatus.SubmittedForApproval; } await _dbManager.SaveAsync("Could not save care package reclaim to database"); return(newReclaim.ToDomain().ToResponse()); }
public async Task <CarePackageReclaimResponse> ExecuteAsync(CarePackageReclaimCreationDomain requestedReclaim) { var package = await _carePackageGateway .GetPackageAsync(requestedReclaim.CarePackageId, PackageFields.Details | PackageFields.Reclaims, true) .EnsureExistsAsync($"Care package {requestedReclaim.CarePackageId} not found"); ValidateReclaim(requestedReclaim, package); // two FNC items are created // - one for the real payment to home, which will be included in Core Cost // - another one is for reclaim, with negative amount, which will compensate payment item. // Just item with FNCPayment sub-type is used in UI / brokerage, reclaim item is for invoicing var fncPayment = CreateReclaimEntity(requestedReclaim, ReclaimSubType.FncPayment); var fncReclaim = CreateReclaimEntity(requestedReclaim, ReclaimSubType.FncReclaim); fncReclaim.Cost = Decimal.Negate(requestedReclaim.Cost); package.Reclaims.Add(fncPayment); package.Reclaims.Add(fncReclaim); package.Histories.Add(new CarePackageHistory { Description = "FNC Created" }); if (package.Status is PackageStatus.Approved) { package.Status = PackageStatus.SubmittedForApproval; } ReclaimCostValidator.Validate(package); await using (var transaction = await _dbManager.BeginTransactionAsync()) { await _createPackageResourceUseCase.CreateFileAsync( package.Id, PackageResourceType.FncAssessmentFile, requestedReclaim.AssessmentFile); await _dbManager.SaveAsync("Could not save FNC reclaim to database"); await transaction.CommitAsync(); } return(fncPayment.ToDomain().ToResponse()); }
public static CarePackageReclaim ToEntity(this CarePackageReclaimCreationDomain input) { return(_mapper.Map <CarePackageReclaim>(input)); }