/// <summary> /// Model Validation /// </summary> /// <param name="validationContext"></param> /// <returns></returns> public IEnumerable <ValidationResult> Validate(ValidationContext validationContext) { var results = new List <ValidationResult>(); // ensure at least one conception model is associated int conceptionModelCount = this.FindAllChildren <Model>().Where(a => typeof(IConceptionModel).IsAssignableFrom(a.GetType())).Count(); if (conceptionModelCount > 1) { string[] memberNames = new string[] { "RuminantType.IConceptionModel" }; results.Add(new ValidationResult(String.Format("Only one Conception component is permitted below the Ruminant Type [r={0}]", Name), memberNames)); } if (this.FindAllChildren <AnimalPricing>().Count() > 1) { string[] memberNames = new string[] { "RuminantType.Pricing" }; results.Add(new ValidationResult(String.Format("Only one Animal pricing schedule is permitted within a Ruminant Type [{0}]", this.Name), memberNames)); } else if (this.FindAllChildren <AnimalPricing>().Count() == 1) { AnimalPricing price = this.FindAllChildren <AnimalPricing>().FirstOrDefault() as AnimalPricing; if (price.FindAllChildren <AnimalPriceGroup>().Count() == 0) { string[] memberNames = new string[] { "RuminantType.Pricing.RuminantPriceGroup" }; results.Add(new ValidationResult(String.Format("At least one Ruminant Price Group is required under an animal pricing within Ruminant Type [{0}]", this.Name), memberNames)); } } return(results); }
private void OnCLEMInitialiseResource(object sender, EventArgs e) { // clone pricelist so model can modify if needed and not affect initial parameterisation if (this.FindAllChildren <AnimalPricing>().Count() > 0) { PriceList = Apsim.Clone(this.FindAllChildren <AnimalPricing>().FirstOrDefault()) as AnimalPricing; priceGroups = PriceList.FindAllChildren <AnimalPriceGroup>().Cast <AnimalPriceGroup>().ToList(); } // get conception parameters and rate calculation method ConceptionModel = this.FindAllChildren <Model>().Where(a => typeof(IConceptionModel).IsAssignableFrom(a.GetType())).Cast <IConceptionModel>().FirstOrDefault(); }
/// <summary> /// Get value of a specific individual with special requirements check (e.g. breeding sire or draught purchase) /// </summary> /// <returns>value</returns> public double ValueofIndividual(Ruminant ind, PurchaseOrSalePricingStyleType purchaseStyle, RuminantFilterParameters property, string value) { double price = 0; if (PricingAvailable()) { string criteria = property.ToString().ToUpper() + ":" + value.ToUpper(); List <Ruminant> animalList = new List <Ruminant>() { ind }; //find first pricing entry matching specific criteria AnimalPriceGroup matchIndividual = null; AnimalPriceGroup matchCriteria = null; foreach (AnimalPriceGroup item in PriceList.FindAllChildren <AnimalPriceGroup>().Cast <AnimalPriceGroup>().Where(a => a.PurchaseOrSale == purchaseStyle || a.PurchaseOrSale == PurchaseOrSalePricingStyleType.Both)) { if (animalList.Filter(item).Count() == 1 && matchIndividual == null) { matchIndividual = item; } // check that pricing item meets the specified criteria. if (item.FindAllChildren <RuminantFilter>().Cast <RuminantFilter>().Where(a => (a.Parameter.ToString().ToUpper() == property.ToString().ToUpper() && a.Value.ToUpper() == value.ToUpper())).Count() > 0) { if (matchCriteria == null) { matchCriteria = item; } else { // multiple price entries were found. using first. value = xxx. if (!WarningsMultipleEntry.Contains(criteria)) { WarningsMultipleEntry.Add(criteria); Summary.WriteWarning(this, "Multiple specific [" + purchaseStyle.ToString() + "] price entries were found for [r=" + ind.Breed + "] where [" + property + "]" + (value.ToUpper() != "TRUE" ? " = [" + value + "]." : ".") + "\nOnly the first entry will be used. Price [" + matchCriteria.Value.ToString("#,##0.##") + "] [" + matchCriteria.PricingStyle.ToString() + "]."); } } } } if (matchCriteria == null) { // report specific criteria not found in price list string warningString = "No [" + purchaseStyle.ToString() + "] price entry was found for [r=" + ind.Breed + "] meeting the required criteria [" + property + "]" + (value.ToUpper() != "TRUE" ? " = [" + value + "]." : "."); if (matchIndividual != null) { // add using the best pricing available for [][] purchases of xx per head warningString += "\nThe best available price [" + matchIndividual.Value.ToString("#,##0.##") + "] [" + matchIndividual.PricingStyle.ToString() + "] will be used."; price = matchIndividual.Value * ((matchIndividual.PricingStyle == PricingStyleType.perKg) ? ind.Weight : 1.0); } else { warningString += "\nNo alternate price for individuals could be found for the individuals. Add a new [r=AnimalPriceGroup] entry in the [r=AnimalPricing] for [" + ind.Breed + "]"; } if (!WarningsNotFound.Contains(criteria)) { WarningsNotFound.Add(criteria); Summary.WriteWarning(this, warningString); } } else { price = matchCriteria.Value * ((matchCriteria.PricingStyle == PricingStyleType.perKg) ? ind.Weight : 1.0); } } return(price); }
/// <summary> /// Get value of a specific individual with special requirements check (e.g. breeding sire or draught purchase) /// </summary> /// <returns>value</returns> public AnimalPriceGroup GetPriceGroupOfIndividual(Ruminant ind, PurchaseOrSalePricingStyleType purchaseStyle, string property, string value, string warningMessage = "") { double price = 0; if (PricingAvailable()) { AnimalPriceGroup animalPrice = (purchaseStyle == PurchaseOrSalePricingStyleType.Purchase) ? ind.CurrentPriceGroups.Buy : ind.CurrentPriceGroups.Sell; if (animalPrice == null || !animalPrice.Filter(ind)) { string criteria = property.ToUpper() + ":" + value.ToUpper(); //find first pricing entry matching specific criteria AnimalPriceGroup matchIndividual = null; AnimalPriceGroup matchCriteria = null; var priceGroups = PriceList.FindAllChildren <AnimalPriceGroup>() .Where(a => a.PurchaseOrSale == purchaseStyle || a.PurchaseOrSale == PurchaseOrSalePricingStyleType.Both); foreach (AnimalPriceGroup priceGroup in priceGroups) { if (priceGroup.Filter(ind) && matchIndividual == null) { matchIndividual = priceGroup; } var suitableFilters = priceGroup.FindAllChildren <FilterByProperty>() .Where(a => (a.PropertyOfIndividual == property) & ( (a.Operator == System.Linq.Expressions.ExpressionType.Equal && a.Value.ToString().ToUpper() == value.ToUpper()) | (a.Operator == System.Linq.Expressions.ExpressionType.NotEqual && a.Value.ToString().ToUpper() != value.ToUpper()) | (a.Operator == System.Linq.Expressions.ExpressionType.IsTrue && value.ToUpper() == "TRUE") | (a.Operator == System.Linq.Expressions.ExpressionType.IsFalse && value.ToUpper() == "FALSE") ) ).Any(); // check that pricing item meets the specified criteria. if (suitableFilters) { if (matchCriteria == null) { matchCriteria = priceGroup; } else // multiple price entries were found. using first. value = xxx. if (!warningsMultipleEntry.Contains(criteria)) { warningsMultipleEntry.Add(criteria); Summary.WriteMessage(this, "Multiple specific [" + purchaseStyle.ToString() + "] price entries were found for [r=" + ind.Breed + "] where [" + property + "]" + (value.ToUpper() != "TRUE" ? " = [" + value + "]." : ".") + "\r\nOnly the first entry will be used. Price [" + matchCriteria.Value.ToString("#,##0.##") + "] [" + matchCriteria.PricingStyle.ToString() + "].", MessageType.Warning); } } } if (matchCriteria == null) { string warningString = warningMessage; if (warningString != "") { // no warning string passed to method so calculate one // report specific criteria not found in price list warningString = "No [" + purchaseStyle.ToString() + "] price entry was found for [r=" + ind.Breed + "] meeting the required criteria [" + property + "]" + (value.ToUpper() != "TRUE" ? " = [" + value + "]." : "."); if (matchIndividual != null) { // add using the best pricing available for [][] purchases of xx per head warningString += "\r\nThe best available price [" + matchIndividual.Value.ToString("#,##0.##") + "] [" + matchIndividual.PricingStyle.ToString() + "] will be used."; price = matchIndividual.Value * ((matchIndividual.PricingStyle == PricingStyleType.perKg) ? ind.Weight : 1.0); } else { warningString += "\r\nNo alternate price for individuals could be found for the individuals. Add a new [r=AnimalPriceGroup] entry in the [r=AnimalPricing] for [" + ind.Breed + "]"; } } if (!warningsNotFound.Contains(criteria)) { warningsNotFound.Add(criteria); Summary.WriteMessage(this, warningString, MessageType.Warning); } } if (purchaseStyle == PurchaseOrSalePricingStyleType.Purchase) { ind.CurrentPriceGroups = (matchCriteria, ind.CurrentPriceGroups.Sell); return(matchCriteria); } else { ind.CurrentPriceGroups = (ind.CurrentPriceGroups.Buy, matchCriteria); return(matchCriteria); } } } return(null); }