public void TestMethodErstelleRechnungen() { List <Rechnung> rechnungen = rechnungsServices.ErstelleRechnungen(); //Rechnung für Kunde1 Rechnungsposition rpos = new Rechnungsposition() { Rechnungspositionsnummer = rechnungen.ElementAt(0).Rechnungspositionen.ElementAt(0).Rechnungspositionsnummer, Kurs = kurs1 }; Rechnungsposition rPos2 = new Rechnungsposition() { Rechnungspositionsnummer = rechnungen.ElementAt(0).Rechnungspositionen.ElementAt(1).Rechnungspositionsnummer, Kurs = kurs2 }; List <Rechnungsposition> rpositions = new List <Rechnungsposition>(); rpositions.Add(rpos); rpositions.Add(rPos2); Rechnung r1 = new Rechnung() { Rechnungsnummer = rechnungen[0].Rechnungsnummer, AbrechnungsZeitraum = new AbrechnungsZeitraumTyp(DateTime.Now.Month, DateTime.Now.Year), Bezahlt = false, Kunde = kunde1, Rechnungspositionen = rpositions }; //Rechnung für Kunde2 Rechnungsposition rPos3 = new Rechnungsposition() { Rechnungspositionsnummer = rechnungen.ElementAt(1).Rechnungspositionen.ElementAt(0).Rechnungspositionsnummer, Kurs = kurs2 }; List <Rechnungsposition> rpositions2 = new List <Rechnungsposition>(); rpositions2.Add(rPos3); Rechnung r2 = new Rechnung() { Rechnungsnummer = rechnungen[1].Rechnungsnummer, AbrechnungsZeitraum = new AbrechnungsZeitraumTyp(DateTime.Now.Month, DateTime.Now.Year), Bezahlt = false, Kunde = kunde2, Rechnungspositionen = rpositions2 }; List <Rechnung> expected = new List <Rechnung>(); expected.Add(r1); expected.Add(r2); //CollectionAssert.AreEqual(expected, rechnungen.ToList()); Assert.AreEqual(2, rechnungen.Count); Assert.AreEqual(3, rechnungen.Sum(r => r.Rechnungspositionen.Count)); }
public List <Rechnung> ErstelleRechnungen() { int monat = DateTime.Now.Month; int year = DateTime.Now.Year; List <Rechnung> rechnungen = new List <Rechnung>(); Dictionary <Kunde, List <Kurs> > kundenKurse = new Dictionary <Kunde, List <Kurs> >(); return(ts.ExecuteInTransaction(() => { var kurse = ks.GetKurseByVeranstaltungszeit(monat, year); foreach (var kurs in kurse) { foreach (var teilnehmer in kurs.Teilnehmer) { if (!kundenKurse.ContainsKey(teilnehmer)) { var listKurse = new List <Kurs>(); listKurse.Add(kurs); kundenKurse.Add(teilnehmer, listKurse); } else { kundenKurse[teilnehmer].Add(kurs); } } } foreach (var pair in kundenKurse) { List <Rechnungsposition> positionen = new List <Rechnungsposition>(); foreach (var kurs in pair.Value) { Rechnungsposition position = new Rechnungsposition() { Kurs = kurs }; positionen.Add(position); } Rechnung r = new Rechnung() { Kunde = pair.Key, AbrechnungsZeitraum = new AbrechnungsZeitraumTyp(monat, year), Bezahlt = false, Rechnungspositionen = positionen }; rechnungen.Add(r); } return repo.SaveAll(rechnungen); })); }
/// <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" } }; } }