dmdb/core/CsvImportProcess.cs

122 lines
5.4 KiB
C#

using System;
using System.IO;
using dezentrale.model;
using System.Collections.Generic;
using dezentrale.model.money;
namespace dezentrale.core
{
public class CsvImportProcess : BackgroundProcess
{
public string FileName { get; set; } = "";
public CsvImportProcess()
{
Caption = "Import CSV Money Transfers";
Steps = 5;
}
protected override bool Run()
{
uint step = 0;
LogTarget.LogLine($"Importing from {FileName}", LogEvent.ELogLevel.Info, "CsvImportProcess");
List<BankTransfer> tmpList = new List<BankTransfer>();
List<string> headlineFields = null;
List<Member> changedMembers = new List<Member>();
CsvFile csv = new CsvFile() { FieldSeparator = ';' };
try
{
LogTarget.StepStarted(++step, "Reading file...");
try
{
csv.ReadFile(FileName);
LogTarget.StepCompleted(step, "Done reading file.", true);
} catch(Exception ex)
{
LogTarget.LogLine($"Error: {ex.Message}", LogEvent.ELogLevel.Error, "CsvImportProcess");
return false;
}
List<List<string>> contents = csv.FileContents;
LogTarget.StepStarted(++step, $"Parsing file ({contents.Count} csv lines, including headline)...");
for(int csvLine = 0; csvLine < contents.Count; csvLine++)
{
List<string> l = contents[csvLine];
if (headlineFields == null)
{
//The first line is expected to have the headline field first, describing the contents
headlineFields = l;
string fields = "";
foreach(string s in l)
{
fields += $"\"{s}\",";
}
LogTarget.LogLine($"Headline fields: {fields}", LogEvent.ELogLevel.Info, "CsvImportProcess");
continue;
}
BankTransfer bt = new BankTransfer(headlineFields, l, FileName, csvLine);
MoneyTransfer duplicate = Program.MoneyTransfers.FindEqualEntry(bt);
if (duplicate != null)
{
LogTarget.LogLine($"Line {csvLine}: is duplicate of MoneyTransfer {duplicate.Id} (ValutaDate {duplicate.ValutaDateString})", LogEvent.ELogLevel.Info, "CsvImportProcess");
LogTarget.LogLine($" ValutaDate: {bt.ValutaDate}, Amount = {bt.AmountString} {bt.Currency}, Reason = \"{bt.TransferReason.Replace('\r', '\\').Replace('\n', '\\')}\"", LogEvent.ELogLevel.Info, "CsvImportProcess");
}
else
{
Program.MoneyTransfers.AddEntry(bt);
tmpList.Add(bt);
}
}
LogTarget.StepCompleted(step, $"Done parsing entries.", true);
LogTarget.StepStarted(++step, $"Assigning found {tmpList.Count} entries to members");
//try to assign transfers to the members
foreach (BankTransfer bt in tmpList)
{
if (bt.Amount < 0)
{
bt.TransferType = MoneyTransfer.eTransferType.RunningCost;
LogTarget.LogLine($"{bt.Id}: (from CSV line {bt.CsvLine}): Amount = {bt.AmountString} --> RunningCost", LogEvent.ELogLevel.Info, "CsvImportProcess");
continue;
}
foreach (Member m in Program.members.Entries)
{
if (m.CheckBankTransfer(bt))
{
LogTarget.LogLine($"{bt.Id}: (from CSV line {bt.CsvLine}): adding to member {m}", LogEvent.ELogLevel.Info, "CsvImportProcess");
bt.TransferType = MoneyTransfer.eTransferType.MembershipPayment;
changedMembers.Add(m);
m.StartLogEvent("Incoming bank transfer", LogEvent.eEventType.MembershipPayment, "automatic");
m.ApplyMoneyTransfer(bt); //this also stores the member entry
bt.AssignFixed = true;
break; //this is important. We don't want to assign this to multiple members.
}
}
if(!bt.AssignFixed)
{
//bt matches no member!
}
}
LogTarget.StepCompleted(step, $"Done assigning entries.", true);
LogTarget.StepStarted(++step, $"Storing money transfers");
//Store bank transfer list
Program.MoneyTransfers.Entries.Sort();
if (!Program.MoneyTransfers.SaveToFile())
return false;
LogTarget.StepCompleted(step, "", true);
return true;
}
catch (Exception ex)
{
LogTarget.LogLine($"Error while processing csv file \"{FileName}\": {ex.Message}", LogEvent.ELogLevel.Error, "CsvImportProcess");
return false;
}
}
}
}