Fixed entry dates bug in calculation.

Added cost overview in details.
This commit is contained in:
Tobias Erbshäußer
2020-06-28 16:44:25 +02:00
parent e656e373e1
commit e89318363b
3 changed files with 103 additions and 18 deletions
+76 -9
View File
@@ -30,13 +30,18 @@ namespace UCalc.Data
public class CostCalculationResult public class CostCalculationResult
{ {
public decimal TotalAmount { get; } public decimal TotalAmount { get; }
public decimal PastAmount { get; }
public decimal FutureAmount { get; }
public string Details { get; } public string Details { get; }
public string DetailsForLandlord { get; } public string DetailsForLandlord { get; }
public bool AffectsTenant { get; } public bool AffectsTenant { get; }
public CostCalculationResult(decimal totalAmount, string details, string detailsForLandlord, bool affectsTenant) public CostCalculationResult(decimal totalAmount, decimal pastAmount, decimal futureAmount, string details,
string detailsForLandlord, bool affectsTenant)
{ {
TotalAmount = totalAmount; TotalAmount = totalAmount;
PastAmount = pastAmount;
FutureAmount = futureAmount;
Details = details; Details = details;
DetailsForLandlord = detailsForLandlord; DetailsForLandlord = detailsForLandlord;
AffectsTenant = affectsTenant; AffectsTenant = affectsTenant;
@@ -121,7 +126,7 @@ namespace UCalc.Data
{ {
if (tenant.EntryDate != null && tenant.EntryDate.Value.IsBetween(billing.StartDate, billing.EndDate)) if (tenant.EntryDate != null && tenant.EntryDate.Value.IsBetween(billing.StartDate, billing.EndDate))
{ {
AddEvent(tenant.EntryDate.Value, tenant, true); AddEvent(tenant.EntryDate.Value.AddDays(-1), tenant, true);
} }
if (tenant.DepartureDate != null && if (tenant.DepartureDate != null &&
@@ -264,7 +269,7 @@ namespace UCalc.Data
details.Append(costPerDay.CeilAmountToString(Constants.InternalPrecision)); details.Append(costPerDay.CeilAmountToString(Constants.InternalPrecision));
details.Append(" €\n\n"); details.Append(" €\n\n");
return costPerDay; return costPerDay.Ceil2(Constants.InternalPrecision);
} }
private static IEnumerable<Flat> AffectedFlats(this Cost cost, Billing billing) private static IEnumerable<Flat> AffectedFlats(this Cost cost, Billing billing)
@@ -455,7 +460,7 @@ namespace UCalc.Data
return totalAmount; return totalAmount;
} }
private static void CalculateCostInPast(Billing billing, Tenant tenant, Cost cost, StringBuilder details, private static decimal CalculateCostInPast(Billing billing, Tenant tenant, Cost cost, StringBuilder details,
IEnumerable<CostEntry> pastCoveringEntries) IEnumerable<CostEntry> pastCoveringEntries)
{ {
details.Append("In vergangener Abrechnung bereits gezahlt (geschätzt) = "); details.Append("In vergangener Abrechnung bereits gezahlt (geschätzt) = ");
@@ -500,9 +505,11 @@ namespace UCalc.Data
details.Append(totalAmount.CeilToString()); details.Append(totalAmount.CeilToString());
details.Append(" €\n"); details.Append(" €\n");
return totalAmount;
} }
private static void CalculateCostInFuture(Billing billing, Tenant tenant, Cost cost, StringBuilder details, private static decimal CalculateCostInFuture(Billing billing, Tenant tenant, Cost cost, StringBuilder details,
IEnumerable<CostEntry> futureCoveringEntries) IEnumerable<CostEntry> futureCoveringEntries)
{ {
details.Append("In nächster Abrechnung erwartet (geschätzt) = "); details.Append("In nächster Abrechnung erwartet (geschätzt) = ");
@@ -547,13 +554,15 @@ namespace UCalc.Data
details.Append(totalAmount.CeilToString()); details.Append(totalAmount.CeilToString());
details.Append(" €\n"); details.Append(" €\n");
return totalAmount;
} }
private static CostCalculationResult CalculateCost(Billing billing, Tenant tenant, Cost cost) private static CostCalculationResult CalculateCost(Billing billing, Tenant tenant, Cost cost)
{ {
if (!AffectsTenant(tenant, cost)) if (!AffectsTenant(tenant, cost))
{ {
return new CostCalculationResult(0, "", "", false); return new CostCalculationResult(0, 0, 0, "", "", false);
} }
var details = new StringBuilder("Kostenpunkt: "); var details = new StringBuilder("Kostenpunkt: ");
@@ -579,12 +588,13 @@ namespace UCalc.Data
details.Append(" €\n"); details.Append(" €\n");
var detailsLandlord = new StringBuilder(details.ToString()); var detailsLandlord = new StringBuilder(details.ToString());
CalculateCostInPast(billing, tenant, cost, detailsLandlord, pastCoveringEntries); var pastAmount = CalculateCostInPast(billing, tenant, cost, detailsLandlord, pastCoveringEntries);
CalculateCostInFuture(billing, tenant, cost, detailsLandlord, futureCoveringEntries); var futureAmount = CalculateCostInFuture(billing, tenant, cost, detailsLandlord, futureCoveringEntries);
details.Append("\n"); details.Append("\n");
detailsLandlord.Append("\n"); detailsLandlord.Append("\n");
return new CostCalculationResult(totalAmount, details.ToString(), detailsLandlord.ToString(), true); return new CostCalculationResult(totalAmount, pastAmount, futureAmount, details.ToString(),
detailsLandlord.ToString(), true);
} }
public static TenantCalculationResult CalculateForTenant(Billing billing, Tenant tenant) public static TenantCalculationResult CalculateForTenant(Billing billing, Tenant tenant)
@@ -630,5 +640,62 @@ namespace UCalc.Data
return new TenantCalculationResult(tenant, costResults, subTotalAmount, totalAmount, details.ToString(), return new TenantCalculationResult(tenant, costResults, subTotalAmount, totalAmount, details.ToString(),
detailsLandlord.ToString()); detailsLandlord.ToString());
} }
public static string CalculateCostOverview(Billing billing)
{
var str = new StringBuilder();
var tenantResults = billing.Tenants.Select(tenant => CalculateForTenant(billing, tenant)).ToList();
decimal landlordAmount = 0;
foreach (var cost in billing.Costs)
{
str.Append("Kostenpunkt: ");
str.Append(cost.Name);
str.Append("\n\n");
var totalAmount = cost.Entries.Aggregate((decimal) 0, (sum, entry) => sum + entry.Amount);
str.Append("Insgesamter Betrag: ");
str.Append(totalAmount.CeilToString());
str.Append(" €\n");
var (tenantAmount, pastTenantAmount, futureTenantAmount) = tenantResults.Aggregate(
new Tuple<decimal, decimal, decimal>(0, 0, 0),
(sum, tenantResult) =>
{
var costResult = tenantResult.Costs[cost];
return new Tuple<decimal, decimal, decimal>(sum.Item1 + costResult.TotalAmount,
sum.Item2 + costResult.PastAmount, sum.Item3 + costResult.FutureAmount);
});
str.Append("Auf Mieter umgelegt:\n");
str.Append("- Unvermietete Wohnungen werden umgelegt: ");
str.Append(cost.ShiftUnrented ? "Ja\n" : "Nein\n");
str.Append("- In dieser Abrechnung: ");
str.Append(tenantAmount.CeilToString());
str.Append(" €\n");
str.Append("- In vergangener Abrechnung (geschätzt): ");
str.Append(pastTenantAmount.CeilToString());
str.Append(" €\n");
str.Append("- In zukünftiger Abrechnung (geschätzt): ");
str.Append(futureTenantAmount.CeilToString());
str.Append(" €\n");
var t = totalAmount - (tenantAmount + pastTenantAmount + futureTenantAmount);
str.Append("Verbleibende Kosten: ");
str.Append(t.CeilToString());
str.Append(" €\n");
landlordAmount += t;
str.Append("\n---\n\n");
}
str.Append("Nicht umgelegte Kosten: ");
str.Append(landlordAmount.CeilToString());
str.Append(" €");
return str.ToString();
}
} }
} }
+2 -2
View File
@@ -15,12 +15,12 @@
<DockPanel Margin="12, 12, 12, 0" <DockPanel Margin="12, 12, 12, 0"
DockPanel.Dock="Top"> DockPanel.Dock="Top">
<Label DockPanel.Dock="Left" <Label DockPanel.Dock="Left"
Content="Mieter:" Content="Details zu:"
Width="180" Width="180"
Foreground="{x:Static local:Constants.SubMainColor}" /> Foreground="{x:Static local:Constants.SubMainColor}" />
<ComboBox <ComboBox
ItemsSource="{Binding Path=Tenants, RelativeSource={RelativeSource AncestorType=pages:DetailsPage}}" ItemsSource="{Binding Path=Items, RelativeSource={RelativeSource AncestorType=pages:DetailsPage}}"
SelectionChanged="OnSelectedTenantChanged" SelectionChanged="OnSelectedTenantChanged"
x:Name="TenantComboBox"> x:Name="TenantComboBox">
<ComboBox.ItemTemplate> <ComboBox.ItemTemplate>
+25 -7
View File
@@ -5,15 +5,26 @@ using UCalc.Models;
namespace UCalc.Pages namespace UCalc.Pages
{ {
public class DetailsItem
{
public Tenant Tenant { get; }
public string Name => Tenant != null ? Tenant.Name : "Kostenübersicht";
public DetailsItem(Tenant tenant)
{
Tenant = tenant;
}
}
public partial class DetailsPage public partial class DetailsPage
{ {
public Model Model { get; set; } public Model Model { get; set; }
private Billing _billing; private Billing _billing;
public ObservableCollection<Tenant> Tenants { get; } public ObservableCollection<DetailsItem> Items { get; }
public DetailsPage() public DetailsPage()
{ {
Tenants = new ObservableCollection<Tenant>(); Items = new ObservableCollection<DetailsItem>();
InitializeComponent(); InitializeComponent();
} }
@@ -28,10 +39,11 @@ namespace UCalc.Pages
} }
_billing = Model.Dump(); _billing = Model.Dump();
Tenants.Clear(); Items.Clear();
Items.Add(new DetailsItem(null));
foreach (var tenant in _billing.Tenants) foreach (var tenant in _billing.Tenants)
{ {
Tenants.Add(tenant); Items.Add(new DetailsItem(tenant));
} }
TenantComboBox.IsEnabled = true; TenantComboBox.IsEnabled = true;
@@ -41,15 +53,21 @@ namespace UCalc.Pages
private void OnSelectedTenantChanged(object sender, SelectionChangedEventArgs e) private void OnSelectedTenantChanged(object sender, SelectionChangedEventArgs e)
{ {
var tenant = (Tenant) ((ComboBox) sender).SelectedItem; var item = (DetailsItem) ((ComboBox) sender).SelectedItem;
if (tenant == null) if (item == null)
{ {
CalculationTextBox.Text = "Bitte wählen Sie einen Mieter aus, um die Berechnungen anzuzeigen."; CalculationTextBox.Text = "Bitte wählen Sie einen Mieter aus, um die Berechnungen anzuzeigen.";
return; return;
} }
var result = BillingCalculator.CalculateForTenant(_billing, tenant); if (item.Tenant == null)
{
CalculationTextBox.Text = BillingCalculator.CalculateCostOverview(_billing);
return;
}
var result = BillingCalculator.CalculateForTenant(_billing, item.Tenant);
CalculationTextBox.Text = result.DetailsForLandlord; CalculationTextBox.Text = result.DetailsForLandlord;
} }