Fertigstellung - Testing fehlt noch
This commit is contained in:
@@ -1,10 +0,0 @@
|
||||
namespace Projekt_Calcan_Conze_Export;
|
||||
|
||||
internal static class Constants
|
||||
{
|
||||
public const string DateFormat = "yyyy-MM-dd";
|
||||
|
||||
public const string Separator = ";";
|
||||
|
||||
public const string MoneyFormat = "F2";
|
||||
}
|
@@ -1,4 +1,6 @@
|
||||
namespace Projekt_Calcan_Conze_Export.Models;
|
||||
using Core;
|
||||
|
||||
namespace Projekt_Calcan_Conze_Export.Models;
|
||||
|
||||
internal class Billing
|
||||
{
|
||||
@@ -74,7 +76,7 @@ internal class BillingPosition
|
||||
|
||||
public double BaseAmount { get; }
|
||||
|
||||
public int Count { get; }
|
||||
public int Count { get; set; }
|
||||
|
||||
public double TotalAmount => this.BaseAmount * this.Count;
|
||||
}
|
@@ -1,8 +1,9 @@
|
||||
using System.Globalization;
|
||||
|
||||
using Projekt_Calcan_Conze_Export;
|
||||
using Projekt_Calcan_Conze_Export.Models;
|
||||
using Microsoft.VisualBasic;
|
||||
using Core;
|
||||
|
||||
using Projekt_Calcan_Conze_Export.Repositories;
|
||||
using Projekt_Calcan_Conze_Export.Repositories;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -83,26 +84,22 @@ try
|
||||
}
|
||||
}
|
||||
|
||||
List<Billing> billings =
|
||||
[
|
||||
new Billing(
|
||||
startDate: startDate.Value,
|
||||
endDate: endDate.Value,
|
||||
customerNumber: clientNumber,
|
||||
customerName: "Max Mustermann",
|
||||
positions:
|
||||
[
|
||||
new BillingPosition(
|
||||
description: "Testposition",
|
||||
baseAmount: 100.0,
|
||||
count: 3)
|
||||
])
|
||||
];
|
||||
string fileName =
|
||||
$"{DateTime.Today.ToString(Constants.DateFormat)}_{clientNumber}_{startDate.Value.ToString(Constants.DateFormat)}_{endDate.Value.ToString(Constants.DateFormat)}.csv";
|
||||
File.WriteAllLines(
|
||||
Path.Combine(directoryPath, fileName),
|
||||
billings.SelectMany(billing => billing.ToCsvLines()));
|
||||
Console.WriteLine();
|
||||
|
||||
var billing = await Database.CreateBilling(startDate.Value, endDate.Value, clientNumber);
|
||||
|
||||
if (billing is null)
|
||||
{
|
||||
Console.WriteLine("Es konnte keine Rechnung erstellt werden.");
|
||||
}
|
||||
else
|
||||
{
|
||||
string fileName =
|
||||
$"{DateTime.Today.ToString(Constants.DateFormat)}_{clientNumber}_{startDate.Value.ToString(Constants.DateFormat)}_{endDate.Value.ToString(Constants.DateFormat)}.csv";
|
||||
string filePath = Path.Combine(directoryPath, fileName);
|
||||
File.WriteAllLines(filePath, billing.ToCsvLines());
|
||||
Console.WriteLine($"Die Rechnung wurde unter \"{filePath}\" abgelegt.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@@ -7,4 +7,12 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MySql.Data" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@@ -0,0 +1,162 @@
|
||||
using System.Data;
|
||||
|
||||
using Core;
|
||||
|
||||
using Projekt_Calcan_Conze_Export.Models;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
using Projekt_Calcan_Conze_Export.Models;
|
||||
|
||||
namespace Projekt_Calcan_Conze_Export.Repositories;
|
||||
|
||||
internal static class Database
|
||||
{
|
||||
public static async Task<Billing?> CreateBilling(DateOnly startDate, DateOnly endDate, string customerNumber)
|
||||
{
|
||||
Billing? billing = null;
|
||||
|
||||
try
|
||||
{
|
||||
await using var dbConnection = new MySqlConnection(Constants.ConnectionString);
|
||||
await dbConnection.OpenAsync();
|
||||
var transaction = await dbConnection.BeginTransactionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
// ensure wasBilled column exists and activityDateTime does not refresh on update
|
||||
var createWasBilledColumnCommand =
|
||||
new MySqlCommand
|
||||
{
|
||||
Connection = dbConnection,
|
||||
Transaction = transaction,
|
||||
CommandText =
|
||||
"""
|
||||
ALTER TABLE activity ADD IF NOT EXISTS wasBilled BIT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE activity CHANGE COLUMN activityDatetime activityDatetime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||
ALTER TABLE activity ALTER COLUMN activityDatetime DROP DEFAULT;
|
||||
"""
|
||||
};
|
||||
await createWasBilledColumnCommand.ExecuteNonQueryAsync();
|
||||
|
||||
// tables: activityType, activity, contract, user, client
|
||||
// one activityType can be assigned to multiple contracts, one contract has one activityType
|
||||
// one contract can have multiple activities, one activity belongs to one contract
|
||||
// one activity has one user, one user can have multiple activities
|
||||
// one user belongs to one client, one client can have multiple users
|
||||
// one contract belongs to one client, one client can have multiple contracts
|
||||
// get all contracts of the client by the client number and the start and end date
|
||||
// include all activities of the contracts
|
||||
// include the client name (column of client table)
|
||||
// only get activities that were not billed yet (wasBilled = 0)
|
||||
var getActivities =
|
||||
new MySqlCommand
|
||||
{
|
||||
Connection = dbConnection,
|
||||
Transaction = transaction,
|
||||
CommandText =
|
||||
"""
|
||||
SELECT
|
||||
activity.id,
|
||||
activity.contractId,
|
||||
contract.amount,
|
||||
contract.description
|
||||
FROM activity
|
||||
JOIN contract ON activity.contractId = contract.id
|
||||
JOIN activityType ON contract.activityTypeId = activityType.id
|
||||
JOIN user ON activity.userId = user.id
|
||||
JOIN client ON contract.clientId = client.id
|
||||
WHERE client.clientno = @clientNumber
|
||||
AND activity.activityDateTime >= @startDate
|
||||
AND activity.activityDateTime <= @endDate
|
||||
AND activity.wasBilled = 0
|
||||
"""
|
||||
};
|
||||
getActivities.Parameters.AddWithValue("@clientNumber", customerNumber);
|
||||
getActivities.Parameters.AddWithValue("@startDate", startDate.ToString("yyyy-MM-dd"));
|
||||
getActivities.Parameters.AddWithValue("@endDate", endDate.ToString("yyyy-MM-dd"));
|
||||
|
||||
await using var activityReader = await getActivities.ExecuteReaderAsync();
|
||||
Dictionary<int, BillingPosition> positions = [];
|
||||
List<int> activityIds = [];
|
||||
|
||||
while (await activityReader.ReadAsync())
|
||||
{
|
||||
activityIds.Add(activityReader.GetInt32("id"));
|
||||
int contractId = activityReader.GetInt32("contractId");
|
||||
|
||||
if (positions.TryGetValue(contractId, out var positionDto))
|
||||
{
|
||||
positionDto.Count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
positions[contractId] =
|
||||
new BillingPosition(
|
||||
description: activityReader.GetString("description"),
|
||||
baseAmount: activityReader.GetDouble("amount"),
|
||||
count: 1);
|
||||
}
|
||||
}
|
||||
|
||||
await activityReader.CloseAsync();
|
||||
|
||||
// get the customer name separately in case we have no activities
|
||||
|
||||
var getCustomerNameCommand =
|
||||
new MySqlCommand
|
||||
{
|
||||
Connection = dbConnection,
|
||||
Transaction = transaction,
|
||||
CommandText =
|
||||
"""
|
||||
SELECT name
|
||||
FROM client
|
||||
WHERE clientno = @clientNumber
|
||||
"""
|
||||
};
|
||||
getCustomerNameCommand.Parameters.AddWithValue("@clientNumber", customerNumber);
|
||||
|
||||
string customerName = await getCustomerNameCommand.ExecuteScalarAsync() as string ?? string.Empty;
|
||||
|
||||
billing =
|
||||
new Billing(
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
customerNumber: customerNumber,
|
||||
customerName: customerName,
|
||||
positions: positions.Values.ToList());
|
||||
|
||||
// set wasBilled to 1 for all retrieved activities
|
||||
|
||||
string activityIdsString = string.Join(',', activityIds.Select((_, i) => $"@activityId{i}"));
|
||||
var updateWasBilledCommand =
|
||||
new MySqlCommand
|
||||
{
|
||||
Connection = dbConnection,
|
||||
Transaction = transaction,
|
||||
CommandText = $"UPDATE activity SET wasBilled = 1 WHERE id IN ({activityIdsString})"
|
||||
};
|
||||
|
||||
for (int i = 0; i < activityIds.Count; i++)
|
||||
{
|
||||
updateWasBilledCommand.Parameters.AddWithValue($"@activityId{i}", activityIds[i]);
|
||||
}
|
||||
|
||||
await updateWasBilledCommand.ExecuteNonQueryAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
throw;
|
||||
}
|
||||
|
||||
await transaction.CommitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("An error occurred while writing to or reading from the database: " + ex.Message);
|
||||
}
|
||||
|
||||
return billing;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user