private static ITry <Amount, IEnumerable <string> > GetReportedValueV1(Dto.Archive archive) { var totals = archive.Totals.ToTry(_ => "Totals file not found.".ToEnumerable()); var data = totals.FlatMap(t => Try.Aggregate(t.Rows.Select(row => Parser.ParseDecimal(row.Values[3])))); return(data.FlatMap(values => Amount.Create(values.Sum(), "EUR"))); }
public static ITry <ArchiveMetadata, IEnumerable <string> > Create(Dto.Archive archive) { var rawMetadata = Try.Create <Dto.ArchiveMetadata, Exception>(_ => JsonConvert.DeserializeObject <Dto.ArchiveMetadata>(archive.Metadata.Content)); return(rawMetadata.MapError(_ => $"Invalid data ({archive.Metadata.Name}).".ToEnumerable()).FlatMap(metadata => { var version = metadata.Version.Match( "1.0", _ => Try.Success <ArchiveVersion, IEnumerable <string> >(ArchiveVersion.v100), "4.0", _ => Try.Success <ArchiveVersion, IEnumerable <string> >(ArchiveVersion.v400), _ => Try.Error <ArchiveVersion, IEnumerable <string> >("Archive version is not supported.".ToEnumerable()) ); var archiveType = version.FlatMap(v => v.Match( ArchiveVersion.v100, u => Try.Success <ArchiveType, IEnumerable <string> >(ArchiveType.Archiving), ArchiveVersion.v400, u => metadata.ArchiveType.Match( "DAY", _ => Try.Success <ArchiveType, IEnumerable <string> >(ArchiveType.Day), "MONTH", _ => Try.Success <ArchiveType, IEnumerable <string> >(ArchiveType.Month), "FISCALYEAR", _ => Try.Success <ArchiveType, IEnumerable <string> >(ArchiveType.FiscalYear), _ => Try.Error <ArchiveType, IEnumerable <string> >($"{nameof(Model.ArchiveType)} is not supported.".ToEnumerable()) ) )); var previousRecordSignature = metadata.PreviousRecordSignature.ToOption().Match( s => Signature.Create(s), _ => Try.Success <Signature, IEnumerable <string> >(null) ); return Try.Aggregate( version, previousRecordSignature, archiveType, (v, s, t) => new ArchiveMetadata(metadata.TerminalIdentification, s.ToOption(), metadata.Created, v, t) ); })); }
public void Aggregate() { var r1 = Try.Aggregate(Success, Success, success: Product2.Create); Assert.Equal(42, r1.Success.Get().ProductValue1); Assert.Equal(42, r1.Success.Get().ProductValue2); var r2 = Try.Aggregate(Success, Error, Product2.Create); Assert.Equal(Exception, r2.Error.Get().First()); var r3 = Try.Aggregate(Error, Error, Product2.Create); Assert.True(r3.Error.Get().SequenceEqual(new[] { Exception, Exception })); var r4 = Try.Aggregate(new[] { Success, Success, Success }); Assert.True(r4.Success.Get().SequenceEqual(new[] { 42, 42, 42 })); var r5 = Try.Aggregate(new[] { Success, Success, Success }, i => i.Sum(), e => e.Count()); Assert.Equal(126, r5); var r6 = Try.Aggregate(new[] { Success, Error, Error }, i => i.Sum(), e => e.Count()); Assert.Equal(2, r6); var r7 = Try.Aggregate(new[] { Success, Error, Success, Error }); Assert.True(r7.Error.Get().SequenceEqual(new[] { Exception, Exception })); }
private static ITry <Amount, IEnumerable <string> > GetReportedValueV4(Dto.Archive archive) { var invoiceFooter = archive.InvoiceFooter.ToTry(_ => "Invoice footer file not found.".ToEnumerable()); var values = invoiceFooter.FlatMap(i => Try.Aggregate(i.Rows.Select(row => Parser.ParseAmount(row.Values[18])))); return(values.Map(v => Amount.Sum(v))); }
public static ITry <InvoicesToSubmit, IEnumerable <Error> > Create(Header header, Invoice[] invoices) { return(Try.Aggregate( ObjectValidations.NotNull(header), invoices.OrEmptyIfNull().ToTry(i => i.Count() >= 1 && i.Count() <= 10000, _ => Error.Create($"{nameof(invoices)} count must be in range [1, 10000].")), (h, i) => new InvoicesToSubmit(h, i.ToArray()) )); }
public static ITry <NegativeRevenue, IEnumerable <Error> > Create(NegativeAmount netValue, NonPositiveAmount vatValue, RevenueInfo info) { return(Try.Aggregate( ObjectValidations.NotNull(netValue), ObjectValidations.NotNull(vatValue), ObjectValidations.NotNull(info), (n, v, i) => new NegativeRevenue(n, v, i) )); }
public static ITry <RetailSalesReceipt, IEnumerable <Error> > Create(InvoiceInfo info, ISequenceStartingWithOne <NonNegativeRevenue> revenueItems, INonEmptyEnumerable <NonNegativePayment> payments) { return(Try.Aggregate( ObjectValidations.NotNull(info), ObjectValidations.NotNull(revenueItems), ObjectValidations.NotNull(payments), (i, r, p) => new RetailSalesReceipt(i, r, p) )); }
public static ITry <Person, IEnumerable <PersonParsingError> > Parse(string name, string age, string height) { // Try.Aggregate method always executes all tries and then aggregates the success results or the errors. It doesn't stop on first error. // You can transform the result into any type you want. This makes it nice and effective way of parsing values and combining the results. return(Try.Aggregate( ParseName(name), ParseAge(age), ParseHeight(height), (n, a, h) => new Person(n, a, h) )); }
public static ITry <Archive, IEnumerable <string> > Parse(Dto.Archive archive) { return(ArchiveMetadata.Create(archive).FlatMap(metadata => { return Try.Aggregate( TaxSummary.Create(archive, metadata.Version), ReportedValue.Create(archive, metadata.Version), Signature.Create(archive.Signature.Content), (taxSummary, reportedValue, signature) => new Archive(metadata, signature, taxSummary, reportedValue) ); })); }
public static ITry <Archive, IEnumerable <string> > CompileArchive(IReadOnlyList <File> files) { var metadata = GetFile(files, "METADATA.json"); var signature = GetFile(files, "SIGNATURE.txt"); var taxTotals = GetOptionalEntry(files, "TAX_TOTALS").Map(e => GetCsvData(e.Content)); var totals = GetOptionalEntry(files, "TOTALS").Map(e => GetCsvData(e.Content)); var invoiceFooter = GetOptionalEntry(files, "INVOICE_FOOTER").Map(e => GetCsvData(e.Content)); return(Try.Aggregate( metadata, signature, (m, s) => new Archive(metadata: m, signature: s, totals: totals, taxTotals: taxTotals, invoiceFooter: invoiceFooter) )); }
public static ITry <SalesInvoice, IEnumerable <Error> > Create( InvoiceInfo info, ISequenceStartingWithOne <NonNegativeRevenue> revenueItems, INonEmptyEnumerable <NonNegativePayment> payments, InvoiceParty counterpart) { return(Try.Aggregate( ObjectValidations.NotNull(info), ObjectValidations.NotNull(revenueItems), ObjectValidations.NotNull(payments), ObjectValidations.NotNull(counterpart), (i, r, p, c) => new SalesInvoice(i, r, p, c) )); }
public static ITry <SimplifiedInvoice, IEnumerable <Error> > Create(InvoiceInfo info, ISequenceStartingWithOne <NonNegativeRevenue> revenueItems, INonEmptyEnumerable <NonNegativePayment> payments) { var result = Try.Aggregate( ObjectValidations.NotNull(info), ObjectValidations.NotNull(revenueItems), ObjectValidations.NotNull(payments), (i, r, p) => IsValidSimplifiedInvoice(i, r).ToTry( t => new SimplifiedInvoice(i, r, p), f => new Error($"{nameof(SimplifiedInvoice)} can only be below or equal to 100 EUR.").ToEnumerable() ) ); return(result.FlatMap(r => r)); }
public static ITry <CreditInvoice, IEnumerable <Error> > Create( InvoiceInfo info, ISequenceStartingWithOne <NegativeRevenue> revenueItems, INonEmptyEnumerable <NegativePayment> payments, InvoiceParty counterPart, long?correlatedInvoice = null) { return(Try.Aggregate( ObjectValidations.NotNull(info), ObjectValidations.NotNull(revenueItems), ObjectValidations.NotNull(payments), ObjectValidations.NotNull(counterPart), (i, r, p, c) => new CreditInvoice(i, r, p, c, correlatedInvoice) )); }
private static ITry <TaxSummary, IEnumerable <string> > GetV4TaxSummary(Dto.Archive archive) { var invoiceFooter = archive.InvoiceFooter.ToTry(_ => "Invoice footer file not found.".ToEnumerable()); return(invoiceFooter.FlatMap(f => { var taxBreakdownNet = Try.Aggregate(f.Rows.Select(row => ParseLineTaxSummary(row.Values[1]))); var taxBreakdownTax = Try.Aggregate(f.Rows.Select(row => ParseLineTaxSummary(row.Values[2]))); return Try.Aggregate( taxBreakdownNet, taxBreakdownTax, (net, tax) => TaxSummary.Sum(net.Concat(tax)) ); })); }
private static ITry <TaxSummary, IEnumerable <string> > GetV1TaxSummary(Dto.Archive archive) { var taxTotals = archive.TaxTotals.ToTry(_ => "Tax totals file not found.".ToEnumerable()); var data = taxTotals.FlatMap(t => Try.Aggregate(t.Rows.Select(row => { return(Try.Aggregate( Parser.ParseDecimal(row.Values[4]), Parser.ParseDecimal(row.Values[10]).FlatMap(v => Amount.Create(v, "EUR")), (r, v) => (TaxRate: new TaxRate(r), TaxValue: v) )); }))); return(data.Map(lines => new TaxSummary(lines.GroupBy(l => l.TaxRate).ToDictionary( g => g.Key, g => Amount.Sum(g.Select(value => value.TaxValue)) )))); }
private static ITry <TaxSummary, IEnumerable <string> > ParseLineTaxSummary(string value) { var rawValues = value.Split('|').Where(v => !String.IsNullOrEmpty(v)); var parsedValues = rawValues.Select(v => { var parts = v.Split(':'); var percentage = Parser.ParseDecimal(parts[0].TrimEnd('%').Trim()); var amount = Parser.ParseAmount(parts[1]); return(percentage.FlatMap(p => amount.Map(a => (Percentage: p / 100, Amount: a)))); }); return(Try.Aggregate(parsedValues).Map(values => { var valuesByTaxRatePercentage = values.GroupBy(v => v.Percentage); var valuesByTaxRate = valuesByTaxRatePercentage.ToDictionary( g => new TaxRate(g.Key), g => Amount.Sum(g.Select(v => v.Amount)) ); return new TaxSummary(valuesByTaxRate); })); }
public static ITry <TaxSummary, IEnumerable <Error> > Create(TaxExemptItem[] taxExempt = null, TaxRateSummary[] taxed = null) { if (taxExempt.IsEmpty() && taxed.IsEmpty()) { return(Try.Error <TaxSummary, IEnumerable <Error> >(Error.Create("Tax summary must contain at least one item."))); } var validTaxExemptItems = taxExempt.ToOption().FlatMap(e => e.AsNonEmpty()).Match( items => items.ToTry(i => i.Count() <= 7, _ => Error.Create("There can only be up to 7 tax exempt items on one invoice.")), _ => Try.Success <INonEmptyEnumerable <TaxExemptItem>, INonEmptyEnumerable <Error> >(null) ); var validTaxRateSummaries = taxed.ToOption().FlatMap(t => t.AsNonEmpty()).Match( summaries => summaries.ToTry(s => s.Count() <= 6, _ => Error.Create("There can only be up to 6 distinct taxed items on one invoice.")), _ => Try.Success <INonEmptyEnumerable <TaxRateSummary>, INonEmptyEnumerable <Error> >(null) ); return(Try.Aggregate( validTaxExemptItems, validTaxRateSummaries, (i, s) => new TaxSummary(taxExempt: i, taxed: s) )); }
private void AggregatingMultipleTriesIntoSingleResult() { // You can combine independent tries into a single value or a list of errors in case any of the tries is erroneous. ITry <int, NetworkOperationError> number1 = Api.GetNumber(); ITry <int, NetworkOperationError> number2 = Api.GetNumber(); ITry <int, NetworkOperationError> number3 = Api.GetNumber(); ITry <int, IEnumerable <NetworkOperationError> > sumOfThreeNumbers = Try.Aggregate( t1: number1, t2: number2, t3: number3, success: (n1, n2, n3) => n1 + n2 + n3 ); // Great examples of aggregating tries can also be found when parsing. See what the Person.Parse method does. ITry <Person, IEnumerable <PersonParsingError> > mom = Person.Parse("Jane Doe", "24", "185"); ITry <Person, IEnumerable <PersonParsingError> > dad = Person.Parse("John Doe", "29", "185"); ITry <Person, IEnumerable <PersonParsingError> > son = Person.Parse("Jimmy Doe", "1", "75"); ITry <(Person Dad, Person Mom, Person Son), IEnumerable <PersonParsingError> > family = Try.Aggregate( t1: mom, t2: dad, t3: son, success: (m, d, s) => (Dad: d, Mom: m, Son: s) ); }
private void AggregatingCollectionOfTries(int numberCount) { IEnumerable <ITry <int, NetworkOperationError> > numbers = Enumerable.Range(0, numberCount).Select(_ => Api.GetNumber()); // Contains all the numbers if their retrieval succeeded. Or all the errors from the ones that failed. Success results are lost in such case. ITry <IEnumerable <int>, IEnumerable <NetworkOperationError> > combinedResult = Try.Aggregate(numbers); }