/// <summary> /// Determines whether the next invoice on a specified meter can be forecasted and if so, will return the forecasted invoice as an Invoice object. /// Returns null if an invoice cannot be forecasted. /// </summary> /// <param name="meterId">id of the meter for which the forecast is required</param> /// <returns>Foecasted Invoice object, or null, wrapped in EMResponse.</returns> public Invoice forecastNextInvoice(int meterId) { Invoice lastInvoice = new Invoice(); try { lastInvoice = mediator.getLastInvoice(meterId); } catch { return null; } Invoice forecastedInvoice = new Invoice(); if (canForecast(meterId)) { forecastedInvoice = forecastInvoice(lastInvoice); } else { return null; } return forecastedInvoice; }
/// <summary> /// Determines if the consumption on the invoice can be validated. /// </summary> /// <param name="invoice">Invoice to validate</param> /// <returns>bool</returns> internal static bool canValidateConsumption(Invoice invoice) { ///can't be validated if there are no meter readings if (invoice.Meter.Register == null | invoice.Meter.Register.Count == 0) return false; return true; }
// validation method /// <summary> /// Validates an invoice that is not on a banded tariff. /// </summary> /// <param name="invoice">Invoice to validate</param> /// <returns>validated Invoice object</returns> internal override Invoice validateCost(Invoice invoice) { if ((bool)invoice.CostCanBeValidated) { ///ALL FIGURES IN POUNDS ///get tariff for this invoice Tariff tariff = getTariff(invoice); ///validate the cost by building up totalConsumptionCost from each band in the tariff ///to do this we need to track how much of the total consumption is covered by each tariff ///so we know how much applies to the next tariff. double remainingConsumption = invoice.KWh; double calculatedkWhCost = 0; foreach (TariffBand band in tariff.Bands) { if (band.UpperkWhLimit != -1) { ///the band contains tariffband data if (band.UpperkWhLimit == 0 | band.UpperkWhLimit > remainingConsumption) { ///there is either no upperlimit for this band, or not enough consumption remains to enter the next band ///therefore all remaining consumption is charged at this rate calculatedkWhCost += remainingConsumption * band.UnitRate; } else { ///upperlimit of this band is less than remaining consumption, therefore charging for the whole band ///adjust remaining consumption remainingConsumption -= band.UpperkWhLimit; ///add cost of consumption in this band to calculated cost calculatedkWhCost += band.UpperkWhLimit * band.UnitRate; } } } double SCdailyRate = standingChargeCostPerDay(invoice); int length = invoiceLengthInDays(invoice); double totalCaluclatedCost = (calculatedkWhCost + (SCdailyRate * length)) / 100; ///convert from p to pounds invoice.CostVariance = invoice.ConsumptionCharge + invoice.StandingCharge - totalCaluclatedCost; ///costs within 2% are considered valid invoice.CostIsValid = (Math.Abs((decimal)invoice.CostVariance) < (decimal)(totalCaluclatedCost * 0.02)); return invoice; } else { return null; } }
internal Invoice forecastInvoice([PexAssumeUnderTest]ForecastingManager target, Invoice lastInvoice) { object[] args = new object[1]; args[0] = (object)lastInvoice; Type[] parameterTypes = new Type[1]; parameterTypes[0] = typeof(Invoice); Invoice result0 = ((MethodBase)(typeof(ForecastingManager).GetMethod("forecastInvoice", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic, (Binder)null, CallingConventions.HasThis, parameterTypes, (ParameterModifier[])null))) .Invoke((object)target, args) as Invoice; Invoice result = result0; return result; // TODO: add assertions to method ForecastingManagerTest.forecastInvoice(ForecastingManager, Invoice) }
public void forecastInvoiceThrowsTargetInvocationException345() { ForecastingManager forecastingManager; Invoice invoice; forecastingManager = new ForecastingManager(); forecastingManager.mediator = (EMMediator)null; Invoice s0 = new Invoice(); s0.Id = 0; s0.PresentRead = 0; s0.PreviousRead = 0; s0.KWh = 0; s0.StandingCharge = 0; s0.ConsumptionCharge = 0; s0.OtherCharge = 0; s0.Checked = false; s0.ConsumptionIsValid = false; s0.CostIsValid = false; s0.BillDate = default(DateTime); s0.StartDate = new DateTime(4611686018427387903L & 563247985000448L, (DateTimeKind)(563247985000448uL >> 62)); s0.EndDate = new DateTime(4611686018427387903L & 563247985000448L, (DateTimeKind)(563247985000448uL >> 62)); s0.CostVariance = 0; s0.KWhVariance = 0; s0.CostCanBeValidated = default(bool?); s0.ConsumptionCanBeValidated = default(bool?); Meter s1 = new Meter(); s1.Id = 0; s1.SerialNo = (string)null; s1.KWhtoCO2ConversionFactor = 0; s1.NumbDigits = 0; s1.Fuel = (string)null; s1.StartDate = default(DateTime); s1.Invoices = (ICollection<Invoice>)null; s1.Notes = (ICollection<Annotation>)null; s1.Tariffs = (ICollection<Tariff>)null; s1.Register = (ICollection<MeterReading>)null; s0.Meter = s1; invoice = this.forecastInvoice(forecastingManager, s0); }
/// <summary> /// Validates an invoice by updated the validation booleans and cost & consumption variances. /// </summary> /// <param name="invoice">Inovice object to validate</param> /// <param name="saveAfterValidation">whether the changes to the invoice should be saved after validation</param> /// <returns>The validated invoice object, regardless of whether it is saved to the database.</returns> public Invoice validateInvoice(Invoice invoice, bool saveAfterValidation) { ///check whether the invoice can be validated and update validation bools invoice.CostCanBeValidated = Validator.canValidateCost(invoice); invoice.ConsumptionCanBeValidated = Validator.canValidateConsumption(invoice); ///validate the consumption element of the invoice (same regardless of tariff type) invoice = Validator.validateConsumption(invoice); if (invoice.CostCanBeValidated.Value) { ///tariff is banded if the first upper limit is > 0 bool tariffIsBanded = (invoice.Meter.Tariffs.ElementAt(0).Bands.ElementAt(0).UpperkWhLimit > 0); if (tariffIsBanded) { ///use consumption banded validator validator = new ConsumptionBandedValidator(); } else { ///use regular validator validator = new UnbandedValidator(); invoice = validator.validateCost(invoice); } invoice = validator.validateCost(invoice); ///update checked bool invoice.Checked = true; } ///save if required if (saveAfterValidation) mediator.DataManager.editInvoice(invoice.Id, invoice); return invoice; }
// validation method /// <summary> /// Validates the cost of an invoice on an unbanded tariff. /// </summary> /// <param name="invoice"></param> /// <returns>the updated invoice object</returns> internal override Invoice validateCost(Invoice invoice) { if ((bool)invoice.CostCanBeValidated) { double unitRate = pencePerkWh(invoice); double standingChargeDailyRate = standingChargeCostPerDay(invoice); int invoiceDuration = invoiceLengthInDays(invoice); int invoicekWh = invoice.KWh; double calcCost = calculateCost((double)invoiceDuration, standingChargeDailyRate, invoicekWh, unitRate); invoice.CostVariance = (invoice.ConsumptionCharge + invoice.StandingCharge) - calcCost; ///costs within 2% are considered valid invoice.CostIsValid = (Math.Abs((decimal)invoice.CostVariance) < (decimal)(calcCost * 0.02)); return invoice; } else { return null; } }
/// <summary> /// Determines whether the cost of the invoice can be validated. /// </summary> /// <param name="invoice">Invoice to validate</param> /// <returns>bool</returns> internal static bool canValidateCost(Invoice invoice) { ///can't be validated if there is no meter associated with the invoice if (invoice.Meter == null) return false; ///can't validate if there are no tariffs on the meter if (invoice.Meter.Tariffs == null | invoice.Meter.Tariffs.Count == 0) return false; ///can't validate if there is no tariff that applies to this invoice ///so sort tariffs by oldest first invoice.Meter.Tariffs = invoice.Meter.Tariffs.OrderBy(t => t.StartDate).ToList(); ///if the oldest is still newer than the date of the invoice then invoice can be validated if (invoice.Meter.Tariffs.ElementAt(0).StartDate > invoice.StartDate) return false; ///can't validate if there are no bands on the tariff if (invoice.Meter.Tariffs.ElementAt(0).Bands == null | invoice.Meter.Tariffs.ElementAt(0).Bands.Count == 0) return false; return true; }
//* * * CREATION METHODS public int createInvoice(int meterId, string billDate, string startDate, string endDate, int kWh, double consumptionCharge, double standingCharge, double otherCharge, int propertyId) { Invoice newInvoice = new Invoice { BillDate = Convert.ToDateTime(billDate), StartDate = Convert.ToDateTime(startDate), EndDate = Convert.ToDateTime(endDate), KWh = kWh, ConsumptionCharge = consumptionCharge, StandingCharge = standingCharge, OtherCharge = otherCharge, }; newInvoice.Meter = mediator.DataManager.getMeter(meterId); int invoiceId = mediator.DataManager.saveInvoice(newInvoice); mediator.validateInvoice(invoiceId, true); mediator.updatePropertyAnnualTotalCost(propertyId); return invoiceId; }
/// <summary> /// Determines the length of an invoice in days /// </summary> /// <param name="invoice">Invoice being validated</param> /// <returns>int - number of days</returns> protected virtual int invoiceLengthInDays(Invoice invoice) { TimeSpan length = invoice.EndDate - invoice.StartDate; return length.Days; }
/// <summary> /// Returns the relevant tariff from the meter to which the invoice is attached. The relevant tariff is the one covering the dates /// of the invoice. /// </summary> /// <param name="invoice">Invoice being validated</param> /// <returns>Tariff object used for validation</returns> protected virtual Tariff getTariff(Invoice invoice) { ///order tariffs on meter from newest to oldest invoice.Meter.Tariffs = invoice.Meter.Tariffs.OrderByDescending(t => t.StartDate).ToList(); ///get the first tariff with matching date range for invoice Tariff currentTariff = invoice.Meter.Tariffs.First(t => invoice.StartDate >= t.StartDate); return currentTariff; }
internal abstract Invoice validateCost(Invoice invoice);
public void forecastInvoiceThrowsTargetInvocationException583() { ForecastingManager forecastingManager; Invoice invoice; forecastingManager = new ForecastingManager(); forecastingManager.mediator = (EMMediator)null; Invoice s0 = new Invoice(); s0.Id = 0; s0.PresentRead = 0; s0.PreviousRead = 0; s0.KWh = 0; s0.StandingCharge = 0; s0.ConsumptionCharge = 0; s0.OtherCharge = 0; s0.Checked = false; s0.ConsumptionIsValid = false; s0.CostIsValid = false; s0.BillDate = default(DateTime); s0.StartDate = new DateTime(4611686018427387903L & 607282404982784L, (DateTimeKind)(607282404982784uL >> 62)); s0.EndDate = default(DateTime); s0.CostVariance = 0; s0.KWhVariance = 0; s0.CostCanBeValidated = default(bool?); s0.ConsumptionCanBeValidated = default(bool?); s0.Meter = (Meter)null; invoice = this.forecastInvoice(forecastingManager, s0); }
public abstract int saveInvoice(Invoice invoice);
public abstract Invoice editInvoice(int invoiceId, Invoice newInvoice);
/// <summary> /// Saves the invoice object to the databse /// </summary> /// <param name="invoice"></param> public override int saveInvoice(Invoice invoice) { emdb.Invoices.Add(invoice); emdb.SaveChanges(); return invoice.Id; }
/// <summary> /// Returns Validator.getTariff - see Validator documentation for more details /// </summary> protected override Tariff getTariff(Invoice invoice) { return base.getTariff(invoice); }
/// <summary> /// Returns the unit rate of the energy for this invoice /// </summary> /// <param name="invoice">the Invoice being validated</param> /// <returns>double containing the unit rate</returns> protected double pencePerkWh(Invoice invoice) { ///call base class to find appropriate triff Tariff tariff = getTariff(invoice); ///UnbandedValidator has been instantiated so we know the rate is just the UnitRate of the first band return tariff.Bands.ElementAt(0).UnitRate; }
/// <summary> /// Assesses the tariff to determine the daily cost in £ of the standing charge /// </summary> /// <param name="invoice">Invoice being validated</param> /// <returns>double £/day cost of standing charge</returns> protected virtual double standingChargeCostPerDay(Invoice invoice) { Tariff tariff = getTariff(invoice); double SCpencePerDay = tariff.SCValue / tariff.SCPeriod.NumbDays * 100; return SCpencePerDay; }
/// <summary> /// Generates a 'dummy' invoice with a kWh amount based on change in performance from the same period last year, then uses validator to calculate the cost /// of the forecasted consumption & standing charge. The invoice is not saved to the database. /// </summary> /// <param name="lastInvoice">most recent invoice on meter, determined using InvoiceManager.getLastInvoice(meterId)</param> /// <returns>Invoice object with forecasted data</returns> private Invoice forecastInvoice(Invoice lastInvoice) { Invoice forecastedInvoice = new Invoice(); TimeSpan lengthOfInvoice = lastInvoice.EndDate - lastInvoice.StartDate; TimeSpan oneDay = new TimeSpan(1, 0, 0, 0); ///to account for seasonality, determine consumption of the same time period one year ago TimeSpan oneYear = new TimeSpan(365, 0, 0, 0); DateTime kWhLastYearStart = lastInvoice.StartDate - oneYear; DateTime kWhLastYearEnd = lastInvoice.EndDate - oneYear; double kWhSameTimeLastYear = mediator.getDataFromMeter(lastInvoice.Meter.Id, kWhLastYearStart.ToString(), kWhLastYearEnd.ToString(), (int)DataType.Energy); ///determine the variance between the kWh consumed in the two time periods - this accounts for change in performance from then to now double variance; ///if kWh used during the same period last year is 0, we have no reason to believe the performance has changed, therefore kWh will be the same ///and the variance will be one ///otherwise the variance is the change in kWh as a percentage of the kWh of the last invoice ///where -ve value means kWh has decreased if (kWhSameTimeLastYear == 0) { variance = 1; } else { variance = (lastInvoice.KWh - kWhSameTimeLastYear) / (double)lastInvoice.KWh; } ///apply variance to give forecasted energy consumption for next invoice forecastedInvoice.KWh = (int)Math.Round( (double)(lastInvoice.KWh) * variance); ///set start and end dates of forecasted invoice forecastedInvoice.StartDate = lastInvoice.StartDate + oneDay; forecastedInvoice.EndDate = forecastedInvoice.StartDate + lengthOfInvoice; ///assign the releveant meter to the invoice as this contains tariff data used to forcast costs forecastedInvoice.Meter = lastInvoice.Meter; ///use validation manager to populated cost variance attribute forecastedInvoice = mediator.validateInvoice(forecastedInvoice, false); if (forecastedInvoice.CostCanBeValidated.Value) { ///use the cost variance to generated forecasted invoice cost ///NB cost variance will be negative since calulated cost is bigger than cost on invoice (0) forecastedInvoice.ConsumptionCharge = 0 - forecastedInvoice.CostVariance; return forecastedInvoice; } else { return null; } }
/// <summary> /// Returns Validator.invoiceLengthInDays - see Validator documentation for more details /// </summary> protected override int invoiceLengthInDays(Invoice invoice) { return base.invoiceLengthInDays(invoice); }
/// <summary> /// Returns Validator.standingChargeCostPerDay - see Validator documentation for more details /// </summary> protected override double standingChargeCostPerDay(Invoice invoice) { return base.standingChargeCostPerDay(invoice); }
public Invoice validateInvoice(Invoice invoice, bool safeAfterValidation) { validationMgr = new ValidationManager(); return validationMgr.validateInvoice(invoice, safeAfterValidation); }
//public List<Chunk> getCostFromMeterByInterval(int meterId, string startDate, string endDate, int intervalId) //{ // Meter meter = mediator.DataManager.getMeter(meterId); // List<Chunk> dataIn = mediator.convertInvoicesToChunks(meter.Invoices.ToList()); // DateTime start = Convert.ToDateTime(startDate); // DateTime end = Convert.ToDateTime(endDate); // AppotionmentPeriod interval = (AppotionmentPeriod)intervalId; // List<Chunk> result = mediator.apportionToPeriod(dataIn, start, end, interval); // return result; //} public string getLastInvoiceDate(int meterId) { Meter meter = mediator.DataManager.getMeter(meterId); Invoice lastInvoice = new Invoice(); ///check for presence of invoices if (meter.Invoices == null | meter.Invoices.Count == 0) { return null; } else { meter.Invoices = meter.Invoices.OrderBy(inv => inv.StartDate).ToList(); lastInvoice = meter.Invoices.ElementAt(0); } return lastInvoice.EndDate.ToShortDateString(); }
/// <summary> /// Validates the consumption kWh firgure of an invoice /// </summary> /// <param name="invoice">Invoice being validated</param> /// <returns>Updated invoice with kWh variation and costIsValid bool</returns> internal static Invoice validateConsumption(Invoice invoice) { if ((bool)invoice.ConsumptionCanBeValidated) { invoice.ConsumptionCanBeValidated = true; ValidationManager validationMgr = new ValidationManager(); double meteredkWh = validationMgr.getDataFromMeter(invoice.Meter.Id, invoice.StartDate.ToString(), invoice.EndDate.ToString(), (int)DataType.Energy); invoice.KWhVariance = invoice.KWh - meteredkWh; ///consumption within 15% is considered valid ///margin of error due to: /// - rounding /// - apportionment estimation invoice.ConsumptionIsValid = (Math.Abs((decimal)invoice.KWhVariance) < (decimal)(meteredkWh * 0.15)); } return invoice; }
/// <summary> /// Updates invoice with specified id. Child objects ARE NOT updated (except meter). /// </summary> /// <param name="invoiceId">id of invoice to update</param> /// <param name="newInvoice">invoice object with replacement data</param> public override Invoice editInvoice(int invoiceId, Invoice newInvoice) { Invoice oldInvoice = emdb.Invoices.Include("Meter").Single(inv => inv.Id == invoiceId); oldInvoice.Meter = emdb.Meters.Find(newInvoice.Meter.Id); oldInvoice.PresentRead = newInvoice.PresentRead; oldInvoice.PreviousRead = newInvoice.PreviousRead; oldInvoice.KWh = newInvoice.KWh; oldInvoice.ConsumptionCharge = newInvoice.ConsumptionCharge; oldInvoice.StandingCharge = newInvoice.StandingCharge; oldInvoice.OtherCharge = newInvoice.OtherCharge; oldInvoice.BillDate = newInvoice.BillDate; oldInvoice.StartDate = newInvoice.StartDate; oldInvoice.EndDate = newInvoice.EndDate; oldInvoice.Checked = newInvoice.Checked; oldInvoice.ConsumptionIsValid = newInvoice.ConsumptionIsValid; oldInvoice.CostIsValid = newInvoice.CostIsValid; emdb.SaveChanges(); return oldInvoice; }