Beispiel #1
0
        /// <summary>
        /// test if Energiemenge has only one <see cref="Mengeneinheit"/>
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <returns>true iff the Energiemenge-&gt;energieverbrauch list does only contain entries with mutually convertible units</returns>
        public static bool IsPureMengeneinheit(this BO4E.BO.Energiemenge em)
        {
            using (MiniProfiler.Current.Step(nameof(IsPureMengeneinheit)))
            {
                ISet <Mengeneinheit> einheiten = new HashSet <Mengeneinheit>();
                em.Energieverbrauch.All <Verbrauch>(v => einheiten.Add(v.Einheit));

                if (einheiten.Count <= 1)
                {
                    return(true);
                }
                else
                {
                    Mengeneinheit me1 = einheiten.First <Mengeneinheit>();
                    foreach (Mengeneinheit me2 in einheiten)
                    {
                        if (!me1.IsConvertibleTo(me2))
                        {
                            return(false);
                        }
                    }
                    return(true);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        ///     returns the factor that is needed to convert an amount in unit <paramref name="me1" /> to an equivalent amount in
        ///     unit <paramref name="me2" />.
        /// </summary>
        /// <param name="me1">source unit</param>
        /// <param name="me2">target unit</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">iff units do not have the same dimension</exception>
        public static decimal GetConversionFactor(this Mengeneinheit me1, Mengeneinheit me2)
        {
#pragma warning disable 618
            if (me1 == Mengeneinheit.ZERO || me2 == Mengeneinheit.ZERO)
#pragma warning restore 618
            {
                throw new InvalidOperationException("You must not use the artificial 'ZERO' value.");
            }

            if (me1 == me2)
            {
                return(1.0M);
            }
            if (!me1.IsConvertibleTo(me2))
            {
                throw new InvalidOperationException(
                          $"{me1} and {me2} are not convertible into each other because they don't share the same dimension.");
            }
            if ((int)me1 % (int)me2 == 0 || (int)me2 % (int)me2 == 0)
            {
                return((decimal)me1 / (decimal)me2);
            }

            throw new InvalidOperationException($"{me1} and {me2} are not (trivially) convertible into each other.");
        }
Beispiel #3
0
        /// <summary>
        /// convert to another unit if possible
        /// </summary>
        /// <param name="v">Verbrauch</param>
        /// <param name="mengeneinheit">Mengeneinheit</param>
        /// <throws>ArgumentException if units are not convertible</throws>
        public static void ConvertToUnit(this Verbrauch v, Mengeneinheit mengeneinheit)
        {
            PhysikalischerWert oldWert = new PhysikalischerWert(v.Wert, v.Einheit);
            PhysikalischerWert newWert = oldWert.ConvertToUnit(mengeneinheit);

            v.Wert    = newWert.Wert;
            v.Einheit = newWert.Einheit;
        }
Beispiel #4
0
        /// <summary>
        ///     Tests if two Mengeneinheit are convertible into each other / do have the same kind.
        /// </summary>
        /// <param name="me1"></param>
        /// <param name="me2"></param>
        /// <returns>true iff convertible</returns>
        public static bool AreConvertible(Mengeneinheit me1, Mengeneinheit me2)
        {
#pragma warning disable 618
            if (me1 == Mengeneinheit.ZERO || me2 == Mengeneinheit.ZERO)
            {
                return(false);
            }
#pragma warning restore 618
            return(DimensionSets.Any(einheitengroup => einheitengroup.Contains(me1) && einheitengroup.Contains(me2)));
        }
 /// <summary>
 /// Tests if two Mengeneinheit are convertible into each other / do have the same kind.
 /// </summary>
 /// <param name="me1"></param>
 /// <param name="me2"></param>
 /// <returns>true iff convertible</returns>
 public static bool AreConvertible(Mengeneinheit me1, Mengeneinheit me2)
 {
     foreach (ISet <Mengeneinheit> einheitengroup in DIMENSION_SETS)
     {
         if (einheitengroup.Contains(me1) && einheitengroup.Contains(me2))
         {
             return(true);
         }
     }
     return(false);
 }
        /// <summary>
        /// initialise with wert and string for einheit
        /// </summary>
        /// <param name="wert">numerischer wert</param>
        /// <param name="einheitString">zugehörige Einheit als string (case insensitive)</param>
        public PhysikalischerWert(decimal wert, string einheitString) : this()
        {
            this.Wert = wert;

            if (!Enum.TryParse <Mengeneinheit>(einheitString, true, out Mengeneinheit einheit))
            {
                throw new ArgumentException($"'{einheitString}' is not a valid Mengeneinheit");
            }
            else
            {
                this.Einheit = einheit;
            }
        }
        private static HashSet <TimeSpan> GetTimeSpans(this BO.Energiemenge em, Wertermittlungsverfahren wev,
                                                       string obis, Mengeneinheit me)
        {
            var result = new HashSet <TimeSpan>();
            var vlist  = new List <Verbrauch>(em.Energieverbrauch);

            vlist.Sort(new VerbrauchDateTimeComparer());
            vlist = vlist.Where(v => v.Wertermittlungsverfahren == wev && v.Obiskennzahl == obis && v.Einheit == me)
                    .ToList();
            for (var i = 1; i < vlist.Count; i++)
            {
                result.Add(vlist[i].Startdatum - vlist[i - 1].Startdatum);
                result.Add(vlist[i].Enddatum - vlist[i - 1].Enddatum);
            }

            return(result);
        }
 /// <summary>
 /// returns the factor that is needed to convert an amount in unit <paramref name="me1"/> to an equivalent amount in unit <paramref name="me2"/>.
 /// </summary>
 /// <param name="me1">source unit</param>
 /// <param name="me2">target unit</param>
 /// <returns></returns>
 /// <exception cref="InvalidOperationException">iff units do not have the same dimension</exception>
 public static decimal GetConversionFactor(this Mengeneinheit me1, Mengeneinheit me2)
 {
     if (me1 == me2)
     {
         return(1.0M);
     }
     if (!me1.IsConvertibleTo(me2))
     {
         throw new InvalidOperationException($"{me1} and {me2} are not convertible into each other because they don't share the same dimension.");
     }
     if ((int)me1 % (int)me2 == 0 || (int)me2 % (int)me2 == 0)
     {
         return((decimal)me1 / (decimal)me2);
     }
     else
     {
         throw new InvalidOperationException($"{me1} and {me2} are not (trivially) convertible into each other.");
     }
 }
Beispiel #9
0
        /// <summary>
        /// Returns the load in an intensive unit for a given point in time.
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <param name="me">an intensive unit (e.g. "kW")</param>
        /// <param name="dt">point in time</param>
        /// <returns>load if Energiemenge BO contains value for specified date time<paramref name="dt"/>, null otherwise</returns>
        public static decimal?GetLoad(this BO4E.BO.Energiemenge em, Mengeneinheit me, DateTime dt)
        {
            if (!me.IsIntensive())
            {
                throw new ArgumentException($"The Mengeneinheit {me} isn't intensive. Calculating the value for a specific point in time doesn't make sense.");
            }
            decimal?result = null;

            foreach (Verbrauch v in em.Energieverbrauch.Where(v => v.Startdatum <= dt && dt < v.Enddatum))
            {
                if (result.HasValue)
                {
                    result += v.Wert;
                }
                else
                {
                    result = v.Wert;
                }
            }
            return(result);
        }
        /// <summary>
        ///     Test, if the single entries/intervals of the energieverbrauch array share the same duration and spacing in time.
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <param name="reference">reference time frame</param>
        /// <param name="wev">Wertermittlungsverfahren</param>
        /// <param name="obis">OBIS-Kennzahl</param>
        /// <param name="me">Mengeneinheit</param>
        /// <param name="allowGaps">set true to allow gaps</param>
        /// <returns>
        ///     True, if all energieverbrauch entries have the same length and their start and enddatum are evenly spaced.
        ///     Also true, if there less than 2 entries in the energieverbrauch array.
        /// </returns>
        public static bool IsEvenlySpaced(this BO.Energiemenge em, ITimeRange reference, Wertermittlungsverfahren wev,
                                          string obis, Mengeneinheit me, bool allowGaps = false)
        {
            HashSet <TimeSpan> startEndDatumPeriods;

            using (MiniProfiler.Current.Step("finding time spans"))
            {
                startEndDatumPeriods = GetTimeSpans(em, wev, obis, me);
            }

            if (startEndDatumPeriods.Count < 2)
            {
                return(true);
            }
            if (allowGaps)
            {
                // each time difference must be a multiple of the smallest difference.
                using (MiniProfiler.Current.Step("Iterating over all time spans"))
                {
                    var minDiff = startEndDatumPeriods.Min().TotalSeconds;
                    foreach (var ts in startEndDatumPeriods)
                    {
                        if (Math.Abs(ts.TotalSeconds % minDiff) != 0)
                        {
                            // use profiler as logger:
                            using (MiniProfiler.Current.Step(
                                       $"Found TimeSpan {ts} with a duration of {ts.TotalSeconds}. This is no multiple of {minDiff} => not evenly spaced."))
                            {
                                return(false);
                            }
                        }
                    }
                }

                return(true);
            }

            // there must be only 1 time difference between all the elements
            return(startEndDatumPeriods.Count <= 1);
        }
Beispiel #11
0
        /// <summary>
        ///     is the Mengeneinheit extensive?
        /// </summary>
        /// <param name="me"></param>
        /// <returns>true iff extensive</returns>
        public static bool IsExtensive(this Mengeneinheit me)
        {
            switch (me)
            {
            case Mengeneinheit.ANZAHL:
                return(true);

            case Mengeneinheit.JAHR:
                return(true);

            case Mengeneinheit.KUBIKMETER:
                return(true);

            case Mengeneinheit.KW:
                return(false);

            case Mengeneinheit.KWH:
                return(true);

            case Mengeneinheit.MONAT:
                return(true);

            case Mengeneinheit.MWH:
                return(true);

            case Mengeneinheit.STUNDE:
                return(true);

            case Mengeneinheit.TAG:
                return(true);

            case Mengeneinheit.WH:
                return(true);

            default:
                return(false);
            }
        }
Beispiel #12
0
 /// <summary>
 /// Same as <see cref="GetAverage(Mengeneinheit, DateTime, DateTime)"/> but without specifying a time slice.
 /// </summary>
 /// <param name="em">Energiemenge</param>
 /// <param name="wev">type of measurement</param>
 /// <param name="obiskennzahl">OBIS</param>
 /// <param name="me">an intensive or extensive unit</param>
 /// <returns>The average for the given Mengeneinheit for the Energiemenge object or null if there was no Verbrauch for the given Mengeneinheit.</returns>
 public static decimal?GetAverage(this BO4E.BO.Energiemenge em,
                                  Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit me)
 {
     return(em.GetAverage(em.GetTimeRange(), wev, obiskennzahl, me));
 }
 /// <summary>
 /// initialise with wert and einheit
 /// </summary>
 /// <param name="wert">numerischer Wert</param>
 /// <param name="einheit">zugehörige Mengeneinheit</param>
 public PhysikalischerWert(decimal wert, Mengeneinheit einheit) : this()
 {
     this.Wert    = wert;
     this.Einheit = einheit;
 }
Beispiel #14
0
        /// <summary>
        /// Converts a PhysikalischerWert to another unit, e.g. from kWh to MWh. This changes the <see cref="PhysikalischerWert.Einheit"/> and the <see cref="PhysikalischerWert.Wert"/> accordingly
        /// </summary>
        /// <param name="pw">physikalischer Wert</param>
        /// <param name="newEinheit">new unit of measurement</param>
        /// <returns>a new instance of PhysikalischerWert having the unit <paramref name="newEinheit"/></returns>
        public static PhysikalischerWert ConvertToUnit(this PhysikalischerWert pw, Mengeneinheit newEinheit)
        {
            decimal factor = pw.Einheit.GetConversionFactor(newEinheit); // throws all the exceptions.

            return(new PhysikalischerWert(factor * pw.Wert, newEinheit));
        }
Beispiel #15
0
        /// <summary>
        /// this constructor creates a BO4E.Rechnung from a JSON serialized SAP print document ("Druckbeleg")
        /// </summary>
        /// <param name="sapPrintDocument">a JSON serialized SAP print document using lowerCamelCase naming convention</param>
        public Rechnung(JObject sapPrintDocument) : this()
        {
            // why is this method so bloated and always tries to access two different keys of the JSON document using the ?? operator?
            // Initially I exported the SAP print document "Druckbeleg") using the SAP library /ui2/cl_json which allows for pretty printing
            // the ALL_UPPER_CASE SAP internal keys to lowerCamelCase. Later on technical constraints in SAP forced me to use a different
            // serialization which is closer to SAPs internal structure and has no lower case keys at all. Furthermore in SAP there is
            // no difference between string.Empty and null; the latter doesn't even exist as a concept.
            JToken infoToken  = sapPrintDocument.SelectToken("erdk") ?? sapPrintDocument.SelectToken("ERDK");
            JToken tErdzToken = sapPrintDocument.SelectToken("tErdz") ?? sapPrintDocument.SelectToken("T_ERDZ");

            if (tErdzToken == null)
            {
                throw new ArgumentException("The SAP print document did not contain a 'tErdz' token. Did you serialize using the right naming convention?");
            }

            Rechnungsnummer  = (infoToken["opbel"] ?? infoToken["OPBEL"]).Value <string>();
            Rechnungsdatum   = new DateTimeOffset(TimeZoneInfo.ConvertTime((infoToken["bldat"] ?? infoToken["BLDAT"]).Value <DateTime>(), CentralEuropeStandardTime.CENTRAL_EUROPE_STANDARD_TIME, TimeZoneInfo.Utc));
            Rechnungsperiode = new Zeitraum()
            {
                Startdatum = new DateTimeOffset(TimeZoneInfo.ConvertTime((tErdzToken[0]["ab"] ?? tErdzToken[0]["AB"]).Value <DateTime>(), CentralEuropeStandardTime.CENTRAL_EUROPE_STANDARD_TIME, TimeZoneInfo.Utc)),
                Enddatum   = new DateTimeOffset(TimeZoneInfo.ConvertTime((tErdzToken[0]["bis"] ?? tErdzToken[0]["BIS"]).Value <DateTime>(), CentralEuropeStandardTime.CENTRAL_EUROPE_STANDARD_TIME, TimeZoneInfo.Utc))
            };
            Faelligkeitsdatum = new DateTimeOffset(TimeZoneInfo.ConvertTime((infoToken["faedn"] ?? infoToken["FAEDN"]).Value <DateTime>(), CentralEuropeStandardTime.CENTRAL_EUROPE_STANDARD_TIME, TimeZoneInfo.Utc));
            Storno            = false;

            decimal          gSteure, gBrutto, vGezahlt, rBrutto;
            var              gNetto           = gSteure = _ = vGezahlt = rBrutto = 0.00M;
            Waehrungscode    waehrungscode    = (Waehrungscode)Enum.Parse(typeof(Waehrungscode), (infoToken["totalWaer"] ?? infoToken["TOTAL_WAER"]).Value <string>());
            Waehrungseinheit waehrungseinheit = (Waehrungseinheit)Enum.Parse(typeof(Waehrungseinheit), (infoToken["totalWaer"] ?? infoToken["TOTAL_WAER"]).Value <string>());
            Mengeneinheit    mengeneinheit    = (Mengeneinheit)Enum.Parse(typeof(Mengeneinheit), (tErdzToken[0]["massbill"] ?? tErdzToken[0]["MASSBILL"]).Value <string>());

            List <Rechnungsposition> rpList = new List <Rechnungsposition>();
            List <Steuerbetrag>      stList = new List <Steuerbetrag>();

            Vorausgezahlt = new Betrag()
            {
                Waehrung = waehrungscode, Wert = 0
            };
            foreach (JToken jrp in tErdzToken)
            {
                string belzart = (jrp["belzart"] ?? jrp["BELZART"]).ToString();
                if (belzart == "IQUANT" || belzart == "ROUND" || belzart == "ROUNDO")
                {
                    continue;
                }
                else
                {
                    Rechnungsposition rp = new Rechnungsposition();
                    decimal           zeitbezogeneMengeWert = 0;
                    if (belzart == "000001")
                    {
                        rp.Positionstext = "ARBEITSPREIS";
                    }
                    else if (belzart == "000003")
                    {
                        rp.Positionstext      = "PAUSCHALE";
                        mengeneinheit         = Mengeneinheit.JAHR;
                        zeitbezogeneMengeWert = (jrp["preisbtr"] ?? jrp["PREISBTR"]).Value <decimal>();
                        rp.ZeitbezogeneMenge  = new Menge()
                        {
                            Einheit = Mengeneinheit.TAG, Wert = zeitbezogeneMengeWert
                        };

                        rp.Einzelpreis = new Preis()
                        {
                            Wert       = decimal.Parse((jrp["zeitant"] ?? jrp["ZEITANT"]).ToString()),
                            Einheit    = waehrungseinheit,
                            Bezugswert = mengeneinheit
                        };
                    }
                    else if (belzart == "000004")
                    {
                        rp.Positionstext = "VERRECHNUNGSPREIS";
                    }
                    else if (belzart == "SUBT")
                    {
                        rp.Positionstext = "zuzüglich Mehrwertsteuer 19,000%";
                    }
                    else if (belzart == "ZHFBP1" || belzart == "CITAX")
                    {
                        rp.Positionstext = belzart;
                    }
                    else
                    {
                        rp.Positionstext = "";
                    }

                    if ((jrp["massbill"] ?? jrp["MASSBILL"]) != null && !string.IsNullOrWhiteSpace((jrp["massbill"] ?? jrp["MASSBILL"]).Value <string>()))
                    {
                        mengeneinheit = (Mengeneinheit)Enum.Parse(typeof(Mengeneinheit), (jrp["massbill"] ?? jrp["MASSBILL"]).Value <string>());
                    }
                    else if ((jrp["timbasis"] ?? jrp["TIMBASIS"]) != null && !string.IsNullOrWhiteSpace((jrp["timbasis"] ?? jrp["TIMBASIS"]).Value <string>()))
                    {
                        if ((jrp["timbasis"] ?? jrp["TIMBASIS"]).Value <string>() == "365")
                        {
                            mengeneinheit        = Mengeneinheit.JAHR;
                            rp.ZeitbezogeneMenge = new Menge()
                            {
                                Einheit = Mengeneinheit.TAG, Wert = zeitbezogeneMengeWert
                            };
                        }
                    }
                    else
                    {
                        mengeneinheit = Mengeneinheit.KWH;
                    }

                    if (rp.Einzelpreis == null)
                    {
                        if ((jrp["preisbtr"] ?? jrp["PREISBTR"]) != null)
                        {
                            rp.Einzelpreis = new Preis()
                            {
                                Wert       = decimal.Parse((jrp["preisbtr"] ?? jrp["PREISBTR"]).ToString()),
                                Einheit    = waehrungseinheit,
                                Bezugswert = mengeneinheit
                            };
                        }
                        else
                        {
                            rp.Einzelpreis = new Preis()
                            {
                                Wert       = 0,
                                Einheit    = waehrungseinheit,
                                Bezugswert = mengeneinheit
                            }
                        };
                    }

                    rp.Positionsnummer = (jrp["belzeile"] ?? jrp["BELZEILE"]).Value <int>();
                    if ((jrp["bis"] ?? jrp["BIS"]) != null && (jrp["bis"] ?? jrp["BIS"]).Value <string>() != "0000-00-00")
                    {
                        rp.LieferungBis = new DateTimeOffset(TimeZoneInfo.ConvertTime((jrp["bis"] ?? jrp["BIS"]).Value <DateTime>(), CentralEuropeStandardTime.CENTRAL_EUROPE_STANDARD_TIME, TimeZoneInfo.Utc));
                    }
                    if ((jrp["ab"] ?? jrp["AB"]) != null && (jrp["ab"] ?? jrp["AB"]).Value <string>() != "0000-00-00")
                    {
                        rp.LieferungVon = new DateTimeOffset(TimeZoneInfo.ConvertTime((jrp["ab"] ?? jrp["AB"]).Value <DateTime>(), CentralEuropeStandardTime.CENTRAL_EUROPE_STANDARD_TIME, TimeZoneInfo.Utc));
                    }
                    if ((jrp["vertrag"] ?? jrp["VERTRAG"]) != null)
                    {
#pragma warning disable CS0618 // Type or member is obsolete
                        rp.VertragskontoId = (jrp["vertrag"] ?? jrp["VERTRAG"]).Value <string>();
#pragma warning restore CS0618 // Type or member is obsolete
                    }

                    if ((jrp["iAbrmenge"] ?? jrp["I_ABRMENGE"]) != null)
                    {
                        rp.PositionsMenge = new Menge()
                        {
                            Wert    = (jrp["iAbrmenge"] ?? jrp["I_ABRMENGE"]).Value <decimal>(),
                            Einheit = mengeneinheit
                        };
                    }

                    if ((jrp["nettobtr"] ?? jrp["NETTOBTR"]) != null)
                    {
                        if (belzart != "SUBT" && belzart != "CITAX")
                        {
                            rp.TeilsummeNetto = new Betrag()
                            {
                                Wert     = (jrp["nettobtr"] ?? jrp["NETTOBTR"]).Value <decimal>(),
                                Waehrung = waehrungscode
                            };
                        }
                        else
                        {
                            rp.TeilsummeNetto = new Betrag()
                            {
                                Wert     = (jrp["sbasw"] ?? jrp["SBASW"]).Value <decimal>(),
                                Waehrung = waehrungscode
                            };
                            Steuerbetrag steuerbetrag = new Steuerbetrag()
                            {
                                Basiswert  = (jrp["sbasw"] ?? jrp["SBASW"]).Value <decimal>(),
                                Steuerwert = (jrp["sbetw"] ?? jrp["SBETW"]).Value <decimal>(),
                                Waehrung   = (Waehrungscode)Enum.Parse(typeof(Waehrungscode), (jrp["twaers"] ?? jrp["TWAERS"]).Value <string>())
                            };
                            decimal steuerProzent;
                            if ((jrp["stprz"] ?? jrp["STPRZ"]) != null && !string.IsNullOrWhiteSpace((jrp["stprz"] ?? jrp["STPRZ"]).Value <string>()))
                            {
                                steuerProzent = decimal.Parse((jrp["stprz"] ?? jrp["STPRZ"]).Value <string>().Replace(",", ".").Trim(), CultureInfo.InvariantCulture);
                            }
                            else
                            {
                                steuerProzent = steuerbetrag.Steuerwert / steuerbetrag.Basiswert * 100.0M;
                            }
                            if ((int)steuerProzent == 19)
                            {
                                steuerbetrag.Steuerkennzeichen = Steuerkennzeichen.UST_19;
                            }
                            else if ((int)steuerProzent == 7)
                            {
                                steuerbetrag.Steuerkennzeichen = Steuerkennzeichen.UST_7;
                            }
                            else
                            {
                                throw new NotImplementedException($"Taxrate Internal '{jrp["taxrateInternal"]}' is not mapped.");
                            }
                            rp.TeilsummeSteuer = steuerbetrag;
                        }
                        if ((jrp["nettobtr"] ?? jrp["NETTOBTR"]).Value <decimal>() <= 0)
                        {
                            Vorausgezahlt = new Betrag()
                            {
                                Waehrung = waehrungscode, Wert = (jrp["nettobtr"] ?? jrp["NETTOBTR"]).Value <decimal>()
                            };
                        }
                    }

                    rp.Zeiteinheit = mengeneinheit;
                    rpList.Add(rp);

                    var be = (jrp["nettobtr"] ?? jrp["NETTOBTR"]);
                    if (be != null)
                    {
                        if (belzart != "SUBT" && belzart != "CITAX") // this will lead to problems in the long run.
                        {
                            gNetto += be.Value <decimal>();
                        }
                        else
                        {
                            Steuerbetrag steuerbetrag = new Steuerbetrag()
                            {
                                Basiswert  = (jrp["sbasw"] ?? jrp["SBASW"]).Value <decimal>(),
                                Steuerwert = (jrp["sbetw"] ?? jrp["SBETW"]).Value <decimal>(),
                                Waehrung   = (Waehrungscode)Enum.Parse(typeof(Waehrungscode), (jrp["twaers"] ?? jrp["TWAERS"]).Value <string>())
                            };
                            decimal steuerProzent;
                            if ((jrp["stprz"] ?? jrp["STPRZ"]) != null && !string.IsNullOrWhiteSpace((jrp["stprz"] ?? jrp["STPRZ"]).Value <string>()))
                            {
                                steuerProzent = decimal.Parse((jrp["stprz"] ?? jrp["STPRZ"]).Value <string>().Replace(",", ".").Trim(), CultureInfo.InvariantCulture);
                            }
                            else
                            {
                                steuerProzent = Math.Round(steuerbetrag.Steuerwert / steuerbetrag.Basiswert * 100.0M);
                            }
                            if (steuerProzent == 19.0M)
                            {
                                steuerbetrag.Steuerkennzeichen = Steuerkennzeichen.UST_19;
                            }
                            else if (steuerProzent == 7.0M)
                            {
                                steuerbetrag.Steuerkennzeichen = Steuerkennzeichen.UST_7;
                            }
                            else
                            {
                                throw new NotImplementedException($"Taxrate Internal '{jrp["taxrateInternal"] ?? jrp["TAXRATE_INTERNAL"]}' is not mapped.");
                            }
                            stList.Add(steuerbetrag);
                            gSteure += be.Value <decimal>();
                        }
                    }
                }
            }
            Steuerbetraege      = stList;
            Rechnungspositionen = rpList;
            gBrutto             = gNetto + gSteure;
            var zZahlen = gBrutto - vGezahlt - rBrutto;
            Gesamtnetto = new Betrag()
            {
                Wert = gNetto, Waehrung = waehrungscode
            };
            Gesamtsteuer = new Betrag()
            {
                Wert = gSteure, Waehrung = waehrungscode
            };
            Gesamtbrutto = new Betrag()
            {
                Wert = gBrutto, Waehrung = waehrungscode
            };
            Zuzahlen = new Betrag()
            {
                Wert = zZahlen, Waehrung = waehrungscode
            };

            Rechnungsersteller = new Geschaeftspartner()
            {
                Geschaeftspartnerrolle = new List <Geschaeftspartnerrolle>()
                {
                    Geschaeftspartnerrolle.LIEFERANT
                },
                Gewerbekennzeichnung = true,
                Anrede         = Anrede.HERR,
                Name1          = "Mein super Lieferant",
                Partneradresse = new Adresse()
                {
                    Strasse      = "Max-Plank-Strasse",
                    Hausnummer   = "8",
                    Postleitzahl = "90190",
                    Landescode   = Landescode.DE,
                    Ort          = "Walldorf"
                }
            };
            Rechnungsempfaenger = new Geschaeftspartner()
            {
                Geschaeftspartnerrolle = new List <Geschaeftspartnerrolle>()
                {
                    Geschaeftspartnerrolle.KUNDE
                },
                Gewerbekennzeichnung = false,
                Anrede         = Anrede.HERR,
                Name1          = "Lustig",
                Name2          = "Peter",
                Partneradresse = new Adresse()
                {
                    Strasse      = "Magnusstraße",
                    Hausnummer   = "20",
                    Postleitzahl = "50672",
                    Landescode   = Landescode.DE,
                    Ort          = "Köln"
                }
            };
        }
    }
Beispiel #16
0
        /// <summary>
        /// Generate a <see cref="CompletenessReport"/> for the given parameters.
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <param name="reference">reference time frame</param>
        /// <param name="wev">Wertermittlungsverfahren</param>
        /// <param name="obiskennzahl">OBIS Kennzahl</param>
        /// <param name="einheit">Mengeneinheit</param>
        /// <returns>the completeness report</returns>
        public static CompletenessReport GetCompletenessReport(this BO4E.BO.Energiemenge em, ITimeRange reference, Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit einheit)
        {
            CompletenessReport result;

            using (MiniProfiler.Current.Step("create completeness report skeleton + find the coverage"))
            {
                result = new CompletenessReport
                {
                    LokationsId = em.LokationsId,
                    Einheit     = einheit,
                    Coverage    = GetCoverage(em, reference, wev, obiskennzahl, einheit),
                    wertermittlungsverfahren = wev,
                    Obiskennzahl             = obiskennzahl,
                    ReferenceTimeFrame       = new Zeitraum
                    {
                        Startdatum = DateTime.SpecifyKind(reference.Start, DateTimeKind.Utc),
                        Enddatum   = DateTime.SpecifyKind(reference.End, DateTimeKind.Utc)
                    },
                };
            }
            if (em.Energieverbrauch != null && em.Energieverbrauch.Count > 0)
            {
                /*using (MiniProfiler.Current.Step("populating time slices of/with missing/null values"))
                 * {
                 *  result.values = em.GetMissingTimeRanges(reference, wev, obis, einheit)
                 *      .Select(mtr => new CompletenessReport.BasicVerbrauch
                 *      {
                 *          startdatum = DateTime.SpecifyKind(mtr.Start, DateTimeKind.Utc),
                 *          enddatum = DateTime.SpecifyKind(mtr.End, DateTimeKind.Utc),
                 *          wert = null
                 *      }).ToList<CompletenessReport.BasicVerbrauch>();
                 * }
                 * using (MiniProfiler.Current.Step("populating time slices existing values"))
                 * {
                 *  result.values.AddRange(
                 *  em.energieverbrauch
                 *  //.AsParallel<Verbrauch>()
                 *  .Where(v => v.obiskennzahl == obis && v.einheit == einheit && v.wertermittlungsverfahren == wev)
                 *  .Select(v => new CompletenessReport.BasicVerbrauch
                 *  {
                 *      startdatum = DateTime.SpecifyKind(v.startdatum, DateTimeKind.Utc),
                 *      enddatum = DateTime.SpecifyKind(v.enddatum, DateTimeKind.Utc),
                 *      wert = v.wert
                 *  })
                 *  .ToList<CompletenessReport.BasicVerbrauch>());
                 * }*/
                using (MiniProfiler.Current.Step("Setting aggregated gaps"))
                {
                    var        nonNullValues = new TimePeriodCollection(em.Energieverbrauch.Select(v => new TimeRange(v.Startdatum, v.Enddatum)));
                    ITimeRange limits;
                    if (result.ReferenceTimeFrame != null && result.ReferenceTimeFrame.Startdatum.HasValue && result.ReferenceTimeFrame.Enddatum.HasValue)
                    {
                        limits = new TimeRange(result.ReferenceTimeFrame.Startdatum.Value, result.ReferenceTimeFrame.Enddatum.Value);
                    }
                    else
                    {
                        limits = null;
                    }
                    var gaps = (new TimeGapCalculator <TimeRange>()).GetGaps(nonNullValues, limits: limits);
                    result.Gaps = gaps.Select(gap => new CompletenessReport.BasicVerbrauch()
                    {
                        Startdatum = gap.Start,
                        Enddatum   = gap.End,
                        Wert       = null
                    }).ToList();
                }

                /*using (MiniProfiler.Current.Step("sorting result"))
                 * {
                 *  result.values.Sort(new BasicVerbrauchDateTimeComparer());
                 * }*/
                if (em.IsPure(checkUserProperties: true))
                {
                    try
                    {
                        foreach (var kvp in em.Energieverbrauch.Where(v => v.UserProperties != null).SelectMany(v => v.UserProperties))
                        {
                            if (result.UserProperties == null)
                            {
                                result.UserProperties = new Dictionary <string, JToken>();
                            }
                            if (!result.UserProperties.ContainsKey(kvp.Key))
                            {
                                result.UserProperties.Add(kvp.Key, kvp.Value);
                            }
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        // ok, there's no Verbrauch with user properties.
                    }
                }
            }

            /*else
             * {
             *  result.coverage = null;
             *  result._errorMessage = "energieverbrauch is empty";
             * }*/
            return(result);
        }
Beispiel #17
0
 /// <summary>
 /// Returns the consumption of a given kind of Mengeneinheit within the specified reference time range.
 /// </summary>
 /// <param name="em">Energiemenge</param>
 /// <param name="reference">reference time frame</param>
 /// <param name="wev">Wertermittlungsverfahren</param>
 /// <param name="obiskennzahl">OBIS number</param>
 /// <param name="me">an extensive unit (e.g. "kWh")</param>
 /// <returns>the consumption within the give time slice <paramref name="reference"/> in the unit passed as <paramref name="me"/></returns>
 public static decimal GetConsumption(this BO4E.BO.Energiemenge em, ITimeRange reference,
                                      Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit me)
 {
     if (!me.IsExtensive())
     {
         throw new ArgumentException($"The Mengeneinheit {me} isn't extensive. Calculating a consumption doesn't make sense.");
     }
     return(em.Energieverbrauch
            .Where(v => v.Wertermittlungsverfahren == wev && v.Obiskennzahl == obiskennzahl && v.Einheit == me)
            //.AsParallel<Verbrauch>()
            .Sum(v => GetOverlapFactor(new TimeRange(v.Startdatum, v.Enddatum), reference, false) * v.Wert));
 }
Beispiel #18
0
        /// <summary>
        /// Get ratio of overlap between given Energiemenge and a reference.
        /// Method is basically just another name for <see cref="GetOverlapFactor(TimeRange, TimeRange, bool)"/>
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <param name="reference">reference time range</param>
        /// <param name="obisKz">OBIS</param>
        /// <param name="mengeneinheit">unit of measurement</param>
        /// <param name="wev">type of measurement</param>
        /// <param name="decimalRounding">post decimals</param>
        /// <returns>value between 0 (no overlap) and 1.0 (100% overlap)</returns>
        public static decimal GetCoverage(this BO4E.BO.Energiemenge em, ITimeRange reference,
                                          Wertermittlungsverfahren wev, string obisKz, Mengeneinheit mengeneinheit, int decimalRounding = 10)
        {
            decimal exactResult;

            using (MiniProfiler.Current.Step($"calculating coverage for list with {em.Energieverbrauch.Count} entries."))
            {
                exactResult = em.Energieverbrauch
                              //.AsParallel<Verbrauch>()
                              .Where <Verbrauch>(v => v.Einheit == mengeneinheit && v.Obiskennzahl == obisKz && v.Wertermittlungsverfahren == wev)
                              .Sum(v => GetOverlapFactor(new TimeRange(v.Startdatum, v.Enddatum), reference, true));
            }
            return(Math.Round(exactResult, decimalRounding));
        }
Beispiel #19
0
 /// <summary>
 ///     Is the Mengeneinheit intensive?
 /// </summary>
 /// <param name="me"></param>
 /// <returns>true iff not extensive</returns>
 public static bool IsIntensive(this Mengeneinheit me)
 {
     return(!IsExtensive(me));
 }
Beispiel #20
0
 /// <summary>
 ///     Similar to AreConvertible but as extension method for me1
 /// </summary>
 /// <param name="me1"></param>
 /// <param name="me2"></param>
 /// <returns></returns>
 public static bool IsConvertibleTo(this Mengeneinheit me1, Mengeneinheit me2)
 {
     return(AreConvertible(me1, me2));
 }
Beispiel #21
0
        /// <summary>
        /// Get average of Mengeneinheit for given time interval
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <param name="reference">reference time frame</param>
        /// <param name="wev">Wertermittlungsverfahren</param>
        /// <param name="obiskennzahl">OBIS</param>
        /// <param name="me">an extensive or intensive unit</param>
        /// <returns>the average value or null if no Verbrauch overlapped with the specified time interval</returns>
        public static decimal?GetAverage(this BO4E.BO.Energiemenge em, TimeRange reference,
                                         Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit me)
        {
            decimal?result             = null;
            decimal overallDenominator = 0.0M;

            foreach (Verbrauch v in em.Energieverbrauch.Where(v => v.Einheit == me))
            {
                decimal overlapFactor = GetOverlapFactor(new TimeRange(v.Startdatum, v.Enddatum), reference, true);
                if (result.HasValue)
                {
                    result += overlapFactor * v.Wert;
                }
                else
                {
                    result = v.Wert;
                }
                overallDenominator += overlapFactor;
            }
            if (result.HasValue)
            {
                return(result / overallDenominator);
            }
            else
            {
                return(result);
            }
        }
Beispiel #22
0
        /// <summary>
        /// Get a list of those time ranges within a reference, where no energieverbrauch entries are defined.
        /// </summary>
        /// <param name="em">Energiemenge</param>
        /// <param name="reference">reference timeframe</param>
        /// <param name="wev">Wertermittlungsverfahren</param>
        /// <param name="obis">OBIS-Kennzahl</param>
        /// <param name="me">Mengeneinheit</param>
        /// <returns></returns>
        public static List <TimeRange> GetMissingTimeRanges(this BO4E.BO.Energiemenge em, ITimeRange reference, Wertermittlungsverfahren wev, string obis, Mengeneinheit me)
        {
            using (MiniProfiler.Current.Step(nameof(GetMissingTimeRanges)))
            {
                IDictionary <Tuple <DateTime, DateTime>, Verbrauch> filteredVerbrauch;
                using (MiniProfiler.Current.Step($"Filtering energieverbrauch on OBIS={obis}, WEV={wev}, Mengeneinheit={me}"))
                {
                    filteredVerbrauch = em.Energieverbrauch
                                        .Where <Verbrauch>(v => v.Wertermittlungsverfahren == wev && v.Obiskennzahl == obis && v.Einheit == me)
                                        .ToDictionary(v => new Tuple <DateTime, DateTime>(v.Startdatum, v.Enddatum), v => v);
                }
                if (filteredVerbrauch.Count < 2)
                {
                    throw new ArgumentException("Not enough entries in energieverbrauch to determine periodicity.");
                }
                if (!IsEvenlySpaced(em, reference, wev, obis, me, true))
                {
                    throw new ArgumentException("The provided Energiemenge is not evenly spaced although gaps are allowed.");
                }
                TimeSpan periodicity = GetTimeSpans(em, wev, obis, me).Min <TimeSpan>();
                if (Math.Abs((reference.Start - em.GetMinDate()).TotalMilliseconds % periodicity.TotalMilliseconds) != 0)
                {
                    throw new ArgumentException($"The absolute difference between reference.start ({reference.Start}) and the minimal date time in the Energiemenge ({em.GetMinDate()}) has to be an integer multiple of the periodicity {periodicity.TotalMilliseconds} but was {(reference.Start - em.GetMinDate()).TotalMilliseconds}.");
                }
                // since it's assured, that the energieverbrauch entries are evenly spaced it doesn't matter which entry we use to determine the duration.
                TimeSpan         duration = filteredVerbrauch.Values.Min(v => v.Enddatum) - filteredVerbrauch.Values.Min(v => v.Startdatum);
                List <TimeRange> result   = new List <TimeRange>();
                using (MiniProfiler.Current.Step("Populating list with time slices in UTC"))
                {
                    for (DateTime dt = reference.Start; dt < reference.End; dt += periodicity)
                    {
                        // use a strict '==' instead of overlap. This is justified because all the other cases are considered beforehand
                        switch (dt.Kind)
                        {
                        case DateTimeKind.Local:
                            throw new ArgumentException("Local DateTime not supported!");

                        case DateTimeKind.Unspecified:
                            dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
                            break;

                        case DateTimeKind.Utc:
                            break;
                        }
                        //using (MiniProfiler.Current.Step("linq where on filtered verbrauch"))
                        //{
                        if (!filteredVerbrauch.ContainsKey(new Tuple <DateTime, DateTime>(dt, dt + duration)))//   Where<Verbrauch>(v => v.startdatum == dt && v.enddatum == dt + duration).Any())
                        {
                            result.Add(new TimeRange(dt, dt + duration));
                        }
                        //}
                    }
                }
                return(result);
            }
        }
 /// <summary>
 ///     Get total consumption for given parameters
 /// </summary>
 /// <param name="em">Energiemenge</param>
 /// <param name="wev">type of measurement</param>
 /// <param name="obiskennzahl">OBIS</param>
 /// <param name="me">unit of measurement</param>
 /// <returns>consumption value</returns>
 public static decimal GetTotalConsumption(this BO.Energiemenge em,
                                           Wertermittlungsverfahren wev, string obiskennzahl, Mengeneinheit me)
 {
     return(em.GetConsumption(em.GetTimeRange(), wev, obiskennzahl, me));
 }