/// <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;
        }