btcpayserver/BTCPayServer/Services/Invoices/Export/InvoiceExport.cs

147 lines
6.6 KiB
C#
Raw Normal View History

2020-06-28 21:44:35 -05:00
using System;
2018-11-30 01:22:39 -06:00
using System.Collections.Generic;
using System.Globalization;
2020-07-30 10:01:56 +09:00
using System.IO;
2018-11-30 01:22:39 -06:00
using System.Linq;
using BTCPayServer.Services.Rates;
2020-07-30 10:01:56 +09:00
using CsvHelper.Configuration;
2018-11-30 01:22:39 -06:00
using Newtonsoft.Json;
namespace BTCPayServer.Services.Invoices.Export
2018-11-30 01:22:39 -06:00
{
public class InvoiceExport
2018-11-30 01:22:39 -06:00
{
public BTCPayNetworkProvider Networks { get; }
public CurrencyNameTable Currencies { get; }
public InvoiceExport(CurrencyNameTable currencies)
{
Currencies = currencies;
}
2018-11-30 01:22:39 -06:00
public string Process(InvoiceEntity[] invoices, string fileFormat)
{
var csvInvoices = new List<ExportInvoiceHolder>();
foreach (var i in invoices)
{
csvInvoices.AddRange(convertFromDb(i));
}
if (String.Equals(fileFormat, "json", StringComparison.OrdinalIgnoreCase))
return processJson(csvInvoices);
else if (String.Equals(fileFormat, "csv", StringComparison.OrdinalIgnoreCase))
return processCsv(csvInvoices);
else
throw new Exception("Export format not supported");
}
private string processJson(List<ExportInvoiceHolder> invoices)
{
2018-11-30 01:22:39 -06:00
var serializerSett = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
var json = JsonConvert.SerializeObject(invoices, Formatting.Indented, serializerSett);
2018-11-30 01:22:39 -06:00
return json;
}
private string processCsv(List<ExportInvoiceHolder> invoices)
{
2020-07-30 10:01:56 +09:00
using StringWriter writer = new StringWriter();
using var csvWriter = new CsvHelper.CsvWriter(writer, new CsvConfiguration(CultureInfo.InvariantCulture), true);
csvWriter.WriteHeader<ExportInvoiceHolder>();
csvWriter.NextRecord();
csvWriter.WriteRecords(invoices);
2020-07-30 10:01:56 +09:00
csvWriter.Flush();
return writer.ToString();
}
2018-11-30 01:22:39 -06:00
private IEnumerable<ExportInvoiceHolder> convertFromDb(InvoiceEntity invoice)
{
var exportList = new List<ExportInvoiceHolder>();
var currency = Currencies.GetNumberFormatInfo(invoice.ProductInformation.Currency, true);
2018-12-18 11:56:12 -06:00
var invoiceDue = invoice.ProductInformation.Price;
2018-11-30 01:22:39 -06:00
// in this first version we are only exporting invoices that were paid
foreach (var payment in invoice.GetPayments())
{
// not accounted payments are payments which got double spent like RBfed
if (!payment.Accounted)
continue;
2018-11-30 01:22:39 -06:00
var cryptoCode = payment.GetPaymentMethodId().CryptoCode;
var pdata = payment.GetCryptoPaymentData();
var pmethod = invoice.GetPaymentMethod(payment.GetPaymentMethodId());
var paidAfterNetworkFees = pdata.GetValue() - payment.NetworkFee;
2020-06-28 17:55:27 +09:00
invoiceDue -= paidAfterNetworkFees * pmethod.Rate;
2018-12-18 11:56:12 -06:00
2018-11-30 01:22:39 -06:00
var target = new ExportInvoiceHolder
{
ReceivedDate = payment.ReceivedTime.UtcDateTime,
2018-11-30 01:22:39 -06:00
PaymentId = pdata.GetPaymentId(),
CryptoCode = cryptoCode,
ConversionRate = pmethod.Rate,
PaymentType = payment.GetPaymentMethodId().PaymentType.ToPrettyString(),
Destination = pdata.GetDestination(),
Paid = pdata.GetValue().ToString(CultureInfo.InvariantCulture),
PaidCurrency = Math.Round(pdata.GetValue() * pmethod.Rate, currency.NumberDecimalDigits).ToString(CultureInfo.InvariantCulture),
2018-12-18 11:56:12 -06:00
// Adding NetworkFee because Paid doesn't take into account network fees
// so if fee is 10000 satoshis, customer can essentially send infinite number of tx
// and merchant effectivelly would receive 0 BTC, invoice won't be paid
// while looking just at export you could sum Paid and assume merchant "received payments"
NetworkFee = payment.NetworkFee.ToString(CultureInfo.InvariantCulture),
InvoiceDue = Math.Round(invoiceDue, currency.NumberDecimalDigits),
OrderId = invoice.OrderId,
StoreId = invoice.StoreId,
2018-11-30 01:22:39 -06:00
InvoiceId = invoice.Id,
InvoiceCreatedDate = invoice.InvoiceTime.UtcDateTime,
InvoiceExpirationDate = invoice.ExpirationTime.UtcDateTime,
InvoiceMonitoringDate = invoice.MonitoringExpiration.UtcDateTime,
#pragma warning disable CS0618 // Type or member is obsolete
2018-12-18 23:24:22 +09:00
InvoiceFullStatus = invoice.GetInvoiceState().ToString(),
InvoiceStatus = invoice.StatusString,
InvoiceExceptionStatus = invoice.ExceptionStatusString,
#pragma warning restore CS0618 // Type or member is obsolete
InvoiceItemCode = invoice.ProductInformation.ItemCode,
InvoiceItemDesc = invoice.ProductInformation.ItemDesc,
InvoicePrice = invoice.ProductInformation.Price,
InvoiceCurrency = invoice.ProductInformation.Currency,
2019-02-17 10:33:40 +01:00
BuyerEmail = invoice.BuyerInformation?.BuyerEmail
2018-11-30 01:22:39 -06:00
};
exportList.Add(target);
}
exportList = exportList.OrderBy(a => a.ReceivedDate).ToList();
2018-11-30 01:22:39 -06:00
return exportList;
}
}
public class ExportInvoiceHolder
{
public DateTime ReceivedDate { get; set; }
public string StoreId { get; set; }
public string OrderId { get; set; }
public string InvoiceId { get; set; }
public DateTime InvoiceCreatedDate { get; set; }
public DateTime InvoiceExpirationDate { get; set; }
public DateTime InvoiceMonitoringDate { get; set; }
2018-11-30 01:22:39 -06:00
public string PaymentId { get; set; }
public string Destination { get; set; }
public string PaymentType { get; set; }
2018-12-18 21:44:51 +09:00
public string CryptoCode { get; set; }
2018-12-18 11:56:12 -06:00
public string Paid { get; set; }
public string NetworkFee { get; set; }
public decimal ConversionRate { get; set; }
2018-12-27 16:48:33 +09:00
public string PaidCurrency { get; set; }
public string InvoiceCurrency { get; set; }
2018-12-18 11:56:12 -06:00
public decimal InvoiceDue { get; set; }
public decimal InvoicePrice { get; set; }
public string InvoiceItemCode { get; set; }
public string InvoiceItemDesc { get; set; }
public string InvoiceFullStatus { get; set; }
public string InvoiceStatus { get; set; }
public string InvoiceExceptionStatus { get; set; }
2019-02-17 10:33:40 +01:00
public string BuyerEmail { get; set; }
2018-11-30 01:22:39 -06:00
}
}