public string RecommendPackageUpgrade(PackageSelectionViewData packageSelectionViewData, List <Package> packages) { // This is the delta amount we will consider for extra payment from the current selected price. const decimal packageUpgradeDelta = 10m; // Find out if there is a package which contains all the selected tests, // and has few more tests available, // and its price is less than or equal to the (current selected tests price + delta amount) if (packages.Any(p => (p.Price <= packageSelectionViewData.OfferPrice + packageUpgradeDelta) && (p.Id != packageSelectionViewData.SelectedPackageId) && (packageSelectionViewData.SelectedPackageId <= 0 || p.Price > packageSelectionViewData.OfferPrice) && (packageSelectionViewData.SelectedTestIds.All(st => p.Tests.Select(t => t.Id).Contains(st))))) { // Get the packages which meet our criteria. var upgradePackageOptions = packages.Where(p => (p.Price <= packageSelectionViewData.OfferPrice + packageUpgradeDelta) && (p.Id != packageSelectionViewData.SelectedPackageId) && (packageSelectionViewData.SelectedPackageId <= 0 || p.Price > packageSelectionViewData.OfferPrice) && (packageSelectionViewData.SelectedTestIds.All( st => p.Tests.Select(t => t.Id).Contains(st)))).ToList(); // If there are more than packages in our new list and there is one package which falls // in our upsell category and its price is more than the current selection then we will // take this out. if (!upgradePackageOptions.IsNullOrEmpty() && upgradePackageOptions.Any(p => p.Price <= packageSelectionViewData.OfferPrice + packageUpgradeDelta && p.Price > packageSelectionViewData.OfferPrice)) { upgradePackageOptions.RemoveAll(p => p.Price <= packageSelectionViewData.OfferPrice); } // This will be the package to which we will recommend to upgrade. Package upgradePackage = null; // This will be the price to which we can recommend to upgrade. var minimumUpgradePrice = packageSelectionViewData.OfferPrice + packageUpgradeDelta; // We will take out the package whcih falls into the set criteria and has minimum price with in that limit. foreach (var upgradePackageOption in upgradePackageOptions) { if (minimumUpgradePrice >= upgradePackageOption.Price) { upgradePackage = upgradePackageOption; minimumUpgradePrice = upgradePackageOption.Price; } } // Get the tests included in the package which is to be recommended with the tests which are not currently selected. // And the additional cost the user has to pay. if (upgradePackage != null) { var upgradePackageTestIds = upgradePackage.Tests.Select(t => t.Id); var testIdsToBeAdded = upgradePackageTestIds.Where(t => !packageSelectionViewData.SelectedTestIds.Contains(t)); var testNamesToBeAdded = packageSelectionViewData.TestViewData.Where(t => testIdsToBeAdded.Contains(t.TestId)).Select( t => t.TestName).ToArray(); if (upgradePackage.Price > packageSelectionViewData.OfferPrice) { return(string.Format( "With additional ${0}, you can buy {1} (Discounted) and you can get screened for {2} also!", Math.Round(minimumUpgradePrice - packageSelectionViewData.OfferPrice, 2), upgradePackage.Name, string.Join(",", testNamesToBeAdded))); } if (upgradePackage.Price < packageSelectionViewData.OfferPrice) { return(string.Format( "Your current order costs ${0}. We recommend you buy {1} as it will cost ${2} less. Further it will include your current selection of tests and {3}.", Math.Round(packageSelectionViewData.OfferPrice, 2), upgradePackage.Name, Math.Round(packageSelectionViewData.OfferPrice - minimumUpgradePrice, 2), string.Join(",", testNamesToBeAdded))); } if (upgradePackage.Price == packageSelectionViewData.OfferPrice) { return(string.Format( "With same price i.e. ${0}, you can buy {1} (Discounted) and can get screened for {2} also!", Math.Round(packageSelectionViewData.OfferPrice, 2), upgradePackage.Name, string.Join(",", testNamesToBeAdded))); } } } return(string.Empty); }
public PackageSelectionViewData Create(long selectedPackageId, List <long> packageTestIds, List <long> independentTestIds, List <Package> packages, List <Test> tests) { var selectedPackage = selectedPackageId > 0 ? packages.Single(p => p.Id == selectedPackageId) : null; var selectedPackageTestIds = selectedPackage != null ? selectedPackage.Tests.Select(t => t.Id) : new List <long>(); if (selectedPackage != null) { packageTestIds = selectedPackage.Tests.Select(t => t.Id).ToList(); } if (selectedPackage == null && !packageTestIds.IsNullOrEmpty()) { independentTestIds = independentTestIds.IsNullOrEmpty() ? new List <long>() : independentTestIds; independentTestIds.AddRange(packageTestIds); packageTestIds.Clear(); } var packageName = selectedPackage == null ? string.Empty : selectedPackage.Name; var packageDescription = selectedPackage == null ? string.Empty : selectedPackage.Description; var selectedTestIds = new List <long>(); if (!packageTestIds.IsNullOrEmpty()) { selectedTestIds.AddRange(packageTestIds); } if (!independentTestIds.IsNullOrEmpty()) { selectedTestIds.AddRange(independentTestIds); } List <string> selectedTestNames = null; if (!selectedTestIds.IsNullOrEmpty()) { if (selectedPackage != null) { independentTestIds = selectedTestIds.Where(st => !selectedPackageTestIds.Contains(st)).ToList(); } if (!independentTestIds.IsNullOrEmpty()) { selectedTestNames = tests.Where(t => independentTestIds.Contains(t.Id)).Select(t => t.Name).ToList(); } } var packageViewData = _packageViewDataFactory.Create(packages); var testViewData = _testViewDataFactory.Create(selectedPackage, selectedTestIds, tests); var packageSelectionViewData = new PackageSelectionViewData { PackageViewData = packageViewData, TestViewData = testViewData, SelectedPackageDescription = packageDescription, SelectedPackageId = selectedPackageId, SelectedPackageName = packageName, SelectedTestIds = selectedTestIds, SelectedPackageTestIds = packageTestIds, IndependentTestNames = selectedTestNames, IndependentTestIds = independentTestIds, OfferPrice = Math.Round(testViewData.Sum(tv => tv.OfferPrice), 2) }; if (packageSelectionViewData.SelectedPackageId > 0 && selectedPackage != null) { var packagePrice = selectedPackage.Price; var selectedTestsNotInPackage = tests.Where(t => selectedTestIds.Contains(t.Id) && !selectedPackageTestIds.Contains(t.Id)).ToList(); var testsPrice = selectedTestsNotInPackage.Sum(t => t.Price); packageSelectionViewData.OfferPrice = packagePrice + testsPrice; } return(packageSelectionViewData); }