public JobApprovalDecision EvaluateRule(JobSheet jobSheet) { // Hard-coded, take as parameter var tenPercent = 10; var fifteenPercent = 15; var tenPercentTotal = ((jobSheet.TotalCost / 100) * tenPercent) + jobSheet.TotalCost; var fifteenPercentTotal = ((jobSheet.TotalCost / 100) * fifteenPercent) + jobSheet.TotalCost; if (jobSheet.ReferenceTotalPrice < tenPercentTotal) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Approved)); } if (jobSheet.ReferenceTotalPrice > tenPercentTotal && jobSheet.ReferenceTotalPrice <= fifteenPercentTotal) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Refered, "Reference price exceed 10%.")); } if (jobSheet.ReferenceTotalPrice > fifteenPercentTotal) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Declined, "Reference price exceed 15%.")); } return(new JobApprovalDecision(JobApprovalDecisionEnum.Declined)); }
public void Setup() { _jobSheet = new JobSheet { Id = Guid.Parse("2ce22be0-98cc-423b-9446-d7a5cf9e6756"), ReferenceHoursInMin = new Random().Next(5, 9), ReferenceTotalPrice = new Random().Next(500, 1000), LaborHourCost = 45, Items = new List <Item>() }; }
public JobApprovalDecision EvaluateRule(JobSheet jobSheet) { var labourHours = jobSheet.Items.Sum(x => x.ItemTime); if (jobSheet.ReferenceHoursInMin > labourHours) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Declined, "Reference hours exceed the actual labour hours.")); } return(new JobApprovalDecision(JobApprovalDecisionEnum.Approved)); }
public JobApprovalDecision EvaluateRule(JobSheet jobSheet) { var exhaust = jobSheet.Items.Where(x => x.GenericCategory == "Exhaust").ToArray(); if (exhaust.Any()) { if (exhaust.Count() > 1) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Declined, "More than one Exhaust.")); } } return(new JobApprovalDecision(JobApprovalDecisionEnum.Approved)); }
public JobApprovalDecision EvaluateRule(JobSheet jobSheet) { var breakPads = jobSheet.Items.Where(x => x.GenericCategory == "Break Pads").ToArray(); var discs = jobSheet.Items.Where(x => x.GenericCategory == "Discs").ToArray(); var missingPads = (!breakPads.Any() && discs.Any()); var missingDiscs = (breakPads.Any() && !discs.Any()); if (missingPads || missingDiscs) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Declined, "Missing pads or discs.")); } return(new JobApprovalDecision(JobApprovalDecisionEnum.Approved)); }
public JobApprovalDecision EvaluateRule(JobSheet jobSheet) { var tyres = jobSheet.Items.Where(x => x.GenericCategory == "Tyres").ToArray(); if (tyres.Any()) { var noOfTyres = tyres.Count(); var notInPair = (noOfTyres % 2) != 0; if (notInPair || noOfTyres > 4) { return(new JobApprovalDecision(JobApprovalDecisionEnum.Declined, "Tyres are either not in Pairs or more than 4.")); } } return(new JobApprovalDecision(JobApprovalDecisionEnum.Approved)); }
public JobApprovalDecision EvaluateAllJobRules(JobSheet jobSheet) { _rules.Add(new TyresChangedInPairsAndMaxFour()); _rules.Add(new BreakPadsAndDiscsChangeTogether()); _rules.Add(new OneExhaust()); _rules.Add(new ReferenceHoursNotExceedTotalHoursOfLabour()); _rules.Add(new OverallDecision()); JobApprovalDecision evalResult = new JobApprovalDecision(); foreach (var rule in _rules) { evalResult = rule.EvaluateRule(jobSheet); if (evalResult.JobApprovalDecisionEnum == JobApprovalDecisionEnum.Declined) { return(evalResult); } } return(evalResult); }
/// <summary> /// Validate Job Sheet by business rules /// </summary> /// <returns>Approval object with approval satus, code and validation messages</returns> public Approval Approve(JobSheet jobSheet) { List <string> validationMessages = new List <string>(); // checking if any data is sent at all if (jobSheet == null) { return(new Approval() { ApprovalStatusCode = 3, ApprovalStatusMessage = "Rejected", ApprovalResponseCode = 200, ApprovalValidationMessages = new List <string>() { "Missing parameters" }, ApprovalTime = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture) }); } #region Common validation // Here starts common validation // 1. Rule: total amount <= 0 // Checking if total amount is less or equals to zero if (jobSheet.TotalAmount <= 0) { validationMessages.Add("Total amount cannot be less or equal to 0"); } // 2. Rule: jobs amount <= 0 // Checking if total jobs amount is greater than zero if (jobSheet.References == null) { validationMessages.Add("Jobs amount cannot be less or equals to 0"); } else if (jobSheet.References.Count == 0) { validationMessages.Add("Jobs amount cannot be less or equals to 0"); } #endregion #region business logic // Here starts business logic // 3. Rule: 2 or 4 tyres var tyresCount = jobSheet.References.Count(r => r.ItemID == 1); if ((tyresCount > 0 && tyresCount % 2 != 0 && tyresCount < 4) || tyresCount > 4) { validationMessages.Add("Tyres must be changed in pairs, min 2, max 4"); } // 4. Rule: Brake discs and pads has to be replaced at the same var brakeDiscs = jobSheet.References.Count(r => r.ItemID == 2); var brakePads = jobSheet.References.Count(r => r.ItemID == 3); if (brakeDiscs != brakePads) { validationMessages.Add("Brake pads and disks must be changed at the same time"); } // 5. Rule: maximum 1 exhaust var exhaustCount = jobSheet.References.Count(r => r.ItemID == 5); if (exhaustCount > 1) { validationMessages.Add("A Job Sheet can only include a maximum of 1 exhaust"); } // 6. Rule: Total hous labour must not exceed the reference number of hours labour var labourTotalTime = jobSheet.References.FindAll(l => l.ItemID == 6).Sum(s => s.UnitTime); var totalTime = jobSheet.References.FindAll(l => l.ItemID != 6).Sum(s => s.UnitTime); if (labourTotalTime > totalTime) { validationMessages.Add("Total hours labour must not exceed the reference number of hours labour"); } #endregion #region conditional logic // To Do: // but at existing moment shows principles of validation // Here goes conditional logic, when we get Approve/Refer/Declive statuses // total price < 10% => Approve (status code 1) // 10% < total price < 15% => Refer (status code 2) // 15% < total price => Decline (status code 3) // 7. Rule: // Total price range less than 10% => Approve // Total price range more than or equals 10% and Total price range less than 15% => Refer // Total price range more than or equals 15% => Decline var TotalReferencePrice = jobSheet.References.FindAll(l => l.ItemID == 6).Sum(s => (s.UnitTime * s.UnitCost)); var TotalPrice = jobSheet.References.FindAll(l => l.ItemID != 6).Sum(s => (s.UnitTime * s.UnitCost)); // Generating difference in percents //var TotalPriceDifferenceInPercent = (TotalPrice - TotalReferencePrice) / TotalReferencePrice * 100; var TotalPriceDifferenceInPercent = (TotalReferencePrice - TotalPrice) / TotalPrice * 100; // Validating if there are no errors and TotalPriceDifferenceInPercent < 10 if (validationMessages.Count == 0 && TotalPriceDifferenceInPercent < 10) { validationMessages.Add("Total difference is less than 10%"); // setting up approved status return(new Approval() { ApprovalStatusCode = 1, ApprovalStatusMessage = "Approve", ApprovalResponseCode = 200, ApprovalValidationMessages = validationMessages, ApprovalTime = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture) }); } // Validating if there are no errors and TotalPriceDifferenceInPercent < 15 else if (validationMessages.Count == 0 && TotalPriceDifferenceInPercent < 15) { validationMessages.Add("Total difference is less than 15%"); // setting up refered status return(new Approval() { ApprovalStatusCode = 2, ApprovalStatusMessage = "Refer", ApprovalResponseCode = 200, ApprovalValidationMessages = validationMessages, ApprovalTime = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture) }); } // otherwise reject else { if (validationMessages.Count == 0) { validationMessages.Add("Total difference is more than or equals 15%"); } // setting up rejected status return(new Approval() { ApprovalStatusCode = 3, ApprovalStatusMessage = "Rejected", ApprovalResponseCode = 200, ApprovalValidationMessages = validationMessages, ApprovalTime = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture) }); } #endregion }
public JobApprovalDecision ApproveJobSheet([FromBody] JobSheet jobSheet) { JobRulesEvaluator jobRulesEvaluator = new JobRulesEvaluator(); return(jobRulesEvaluator.EvaluateAllJobRules(jobSheet)); }
public JobApprovalDecision EvaluateBreakPadsAndDiscsChangeTogetherRule(JobSheet jobSheet) { IJobApprovalRule rules = new BreakPadsAndDiscsChangeTogether(); return(rules.EvaluateRule(jobSheet)); }
public MainWindow() { CurrentJobSheet = new JobSheet(); InitializeComponent(); }
public Approval Approve([FromBody] JobSheet jobSheet) { return(_approvalService.Approve(jobSheet)); }
public JobApprovalDecision EvaluateTyresChangedInPairsAndMaxFourRule(JobSheet jobSheet) { IJobApprovalRule rules = new TyresChangedInPairsAndMaxFour(); return(rules.EvaluateRule(jobSheet)); }
public JobApprovalDecision EvaluateReferenceHoursNotExceedTotalHoursOfLabourRule(JobSheet jobSheet) { IJobApprovalRule rules = new ReferenceHoursNotExceedTotalHoursOfLabour(); return(rules.EvaluateRule(jobSheet)); }
public JobApprovalDecision EvaluateOverallDecisionRule(JobSheet jobSheet) { IJobApprovalRule rules = new OverallDecision(); return(rules.EvaluateRule(jobSheet)); }
public JobApprovalDecision EvaluateOneExhaustRule(JobSheet jobSheet) { IJobApprovalRule rules = new OneExhaust(); return(rules.EvaluateRule(jobSheet)); }
public Repository() { _jobSheets = new List <JobSheet>(); var tyreOne = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Tyres", UnitCost = 200, ItemName = "Tyre", ItemTime = 30 }; var tyreTwo = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Tyres", UnitCost = 200, ItemName = "Tyre", ItemTime = 30 }; var tyreThree = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Tyres", UnitCost = 200, ItemName = "Tyre", ItemTime = 30 }; var tyreFour = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Tyres", UnitCost = 200, ItemName = "Tyre", ItemTime = 30 }; var breakPads = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Break Pads", UnitCost = 50, ItemName = "Pads", ItemTime = 60 }; var discs = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Discs", UnitCost = 90, ItemName = "Discs", ItemTime = 100 }; var oil5Liters = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Oil", UnitCost = 20, ItemName = "Oil 5 Lt", ItemTime = 30 }; var oil10Liters = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Oil", UnitCost = 40, ItemName = "Oil 10 Lt", ItemTime = 30 }; var exhaust = new Item { ItemId = Guid.NewGuid(), GenericCategory = "Exhaust", UnitCost = 175, ItemName = "Exhaust", ItemTime = 240 }; var tyresBreakPadsDiscs = new List <Item> { tyreOne, tyreTwo, tyreThree, breakPads, discs }; var js1 = new JobSheet { Id = Guid.Parse("00000000-0000-0000-0000-000000000001"), ReferenceHoursInMin = tyresBreakPadsDiscs.Sum(x => x.ItemTime), ReferenceTotalPrice = (_labourCostHour * tyresBreakPadsDiscs.Sum(x => x.ItemTime) / 60) + (tyresBreakPadsDiscs.Sum(x => x.UnitCost)), LaborHourCost = _labourCostHour, Items = tyresBreakPadsDiscs }; var exhaustOilTyres = new List <Item> { exhaust, oil5Liters, tyreOne, tyreTwo }; var js2 = new JobSheet { Id = Guid.Parse("00000000-0000-0000-0000-000000000002"), ReferenceHoursInMin = exhaustOilTyres.Sum(x => x.ItemTime), ReferenceTotalPrice = (_labourCostHour * exhaustOilTyres.Sum(x => x.ItemTime) / 60) + (exhaustOilTyres.Sum(x => x.UnitCost)), LaborHourCost = _labourCostHour, Items = exhaustOilTyres }; var breakPadsDiscsOil5LitersTyres = new List <Item> { breakPads, discs, oil5Liters, tyreOne, tyreTwo }; var js3 = new JobSheet { Id = Guid.Parse("00000000-0000-0000-0000-000000000003"), ReferenceHoursInMin = breakPadsDiscsOil5LitersTyres.Sum(x => x.ItemTime), ReferenceTotalPrice = (_labourCostHour * breakPadsDiscsOil5LitersTyres.Sum(x => x.ItemTime) / 60) + (breakPadsDiscsOil5LitersTyres.Sum(x => x.UnitCost)), LaborHourCost = _labourCostHour, Items = breakPadsDiscsOil5LitersTyres }; _jobSheets.Add(js1); _jobSheets.Add(js2); _jobSheets.Add(js3); }
/// <summary> /// Get all reference items generated randomly /// </summary> /// <returns>item containing references and total amount</returns> public JobSheet GetItem() { // Initiating random generator Random rng = new Random(); // Generating random Job Sheet List <Reference> references = Enumerable.Range(1, rng.Next(1, 5)).Select(index => new Reference { ItemID = index, ItemTitle = Titles[rng.Next(Titles.Length)], UnitTime = rng.Next(30, 240), UnitCost = (float)rng.Next(20, 200), MustInclude = false }).ToList <Reference>(); // Updating Item IDs and Labor property references.ForEach(delegate(Reference reference) { reference.ItemID = Array.IndexOf(Titles, reference.ItemTitle) + 1; reference.MustInclude = (reference.ItemTitle == "Labor" ? true : false); }); //// Getting Labor if any exist //List<Reference> labours = references.FindAll(l => l.ItemID == 6); //// if none, add one //if (labours.Count == 0) //{ // references.Add(new Reference() // { // ItemID = 6, // ItemTitle = "Labor", // UnitTime = 60, // UnitCost = 45.00f, // MustInclude = true // }); //} // Add labor as it has to have at least one labor references.Add(new Reference() { ItemID = 6, ItemTitle = "Labor", UnitTime = 60, UnitCost = 45.00f, MustInclude = true }); // Genarating job sheet with random property values and total amount JobSheet jobsheet = new JobSheet() { TotalAmount = references.Sum(s => s.UnitTime * s.UnitCost), References = references //References = new List<Reference>() { // new Reference // { // ItemTitle = "Tyre", // UnitTime = 30, // UnitCost = 200.00f // }, // new Reference // { // ItemTitle = "Brake Discs", // UnitTime = 90, // UnitCost = 100.00f // }, // new Reference // { // ItemTitle = "Brake Pads", // UnitTime = 60, // UnitCost = 50.00f // }, // new Reference // { // ItemTitle = "Oil", // UnitTime = 30, // UnitCost = 20.00f // }, // new Reference // { // ItemTitle = "Exhaust", // UnitTime = 240, // UnitCost = 175.00f // } //} }; return(jobsheet); }