PIbd-22_Ulybin_A.A._FuelAccounting_Lab04 #7

Closed
qkrlnt wants to merge 5 commits from Lab04 into Lab03
27 changed files with 254 additions and 91 deletions

View File

@ -1,4 +1,5 @@
using FuelAccounting.Entities.Enums;
using System.ComponentModel;
namespace FuelAccounting.Entities;
@ -6,12 +7,18 @@ public class Car
{
public int Id { get; private set; }
[DisplayName("Модель")]
public string Model { get; private set; } = string.Empty;
[DisplayName("Категория")]
public CarCategory Category { get; private set; }
[Browsable(false)]
public int DriverID { get; private set; }
[DisplayName("Закрепленный водитель")]
public string DriverName { get; private set; } = string.Empty;
public static Car CreateEntity(int id, string model, CarCategory category, int driverId)
{
return new Car

View File

@ -1,4 +1,5 @@
using FuelAccounting.Entities.Enums;
using System.ComponentModel;
namespace FuelAccounting.Entities;
@ -6,10 +7,15 @@ public class Driver
{
public int Id { get; private set; }
[DisplayName("Имя")]
public string FirstName { get; private set; } = string.Empty;
[DisplayName("Фамилия")]
public string LastName { get; private set; } = string.Empty;
public string DriverName => $"{FirstName} {LastName}";
[DisplayName("Категория прав")]
public DriverLicenceCategory DriverLicenceCategory { get; private set; }
public static Driver CreateEntity(int id, string firstName, string lastName, DriverLicenceCategory driverLicenceCategory)

View File

@ -1,17 +1,38 @@
namespace FuelAccounting.Entities;
using System.ComponentModel;
namespace FuelAccounting.Entities;
public class Equipage
{
public int Id { get; private set; }
[Browsable(false)]
public int CarId { get; private set; }
[Browsable(false)]
public int DriverId { get; private set; }
[Browsable(false)]
public int ShiftId { get; private set; }
[Browsable(false)]
public IEnumerable<RoutesEqipage> RoutesEqipage { get; private set; } = [];
[DisplayName("Автомобиль")]
public string CarModel { get; private set; } = string.Empty;
[DisplayName("Водитель")]
public string DriverName { get; private set; } = string.Empty;
[DisplayName("Смена")]
public string ShiftDescription { get; private set; } = string.Empty;
[DisplayName("Маршруты")]
public string Route => RoutesEqipage != null ?
string.Join(", ", RoutesEqipage.Select(x => $"{x.RouteDescription} {x.Count}")) :
string.Empty;
[DisplayName("Дата выезда")]
public DateTime EquipageDate { get; private set; }
public static Equipage CreateOperation(int id, int carId, int driverId, int shiftId, IEnumerable<RoutesEqipage> routesEqipage)
@ -27,17 +48,11 @@ public class Equipage
};
}
public static Equipage CreateOperation(TempRoutesEquipage tempRoutesEquipage,
IEnumerable<RoutesEqipage> routesEqipage)
public void SetRoutesEquipage(IEnumerable<RoutesEqipage> routesEquipage)
{
return new Equipage
if (routesEquipage != null && routesEquipage.Any())
{
Id = tempRoutesEquipage.Id,
CarId = tempRoutesEquipage.CarId,
DriverId = tempRoutesEquipage.DriverId,
ShiftId = tempRoutesEquipage.ShiftId,
RoutesEqipage = routesEqipage,
EquipageDate = tempRoutesEquipage.EquipageDate
};
RoutesEqipage = routesEquipage;
}
}
}

View File

@ -1,19 +1,30 @@
namespace FuelAccounting.Entities;
using System.ComponentModel;
namespace FuelAccounting.Entities;
public class Refueling
{
public int Id { get; private set; }
[Browsable(false)]
public int CarId { get; private set; }
[DisplayName("Автомобиль")]
public string CarModel { get; private set; } = string.Empty;
[DisplayName("Километров пойдено")]
public double Kilometers { get; private set; }
[DisplayName("Литров заправлено")]
public double LitersSpent { get; private set; }
[DisplayName("Тип топлива")]
public string TypeOfFuel { get; private set; } = string.Empty;
[DisplayName("Дата заправки")]
public DateTime RefuelingDate { get; private set; }
public static Refueling CreateOperation(int id, int carId, double kilometers, double litersSpent, string typeOfFuel)
{
return new Refueling

View File

@ -1,11 +1,15 @@
namespace FuelAccounting.Entities;
using System.ComponentModel;
namespace FuelAccounting.Entities;
public class Route
{
public int Id { get; private set; }
[DisplayName("Описание")]
public string Description { get; private set; } = string.Empty;
public static Route CreateEntity(int id, string description)
{
return new Route

View File

@ -6,6 +6,8 @@ public class RoutesEqipage
public int RouteId { get; private set; }
public string RouteDescription { get; private set; } = string.Empty;
public int Count { get; private set; }
public static RoutesEqipage CreateElement(int id, int routeId, int count)

View File

@ -1,11 +1,15 @@
namespace FuelAccounting.Entities;
using System.ComponentModel;
namespace FuelAccounting.Entities;
public class Shift
{
public int Id { get; private set; }
[DisplayName("Количество часов")]
public int AmountOfHours { get; private set; }
[DisplayName("Описание")]
public string Description { get; private set; } = string.Empty;
public static Shift CreateEntity(int id, int amountOfHours, string description)

View File

@ -1,18 +0,0 @@
namespace FuelAccounting.Entities;
public class TempRoutesEquipage
{
public int Id { get; private set; }
public int CarId { get; private set; }
public int DriverId { get; private set; }
public int ShiftId { get; private set; }
public int RouteId { get; private set; }
public int Count { get; private set; }
public DateTime EquipageDate { get; private set; }
}

View File

@ -52,9 +52,9 @@
label2.AutoSize = true;
label2.Location = new Point(12, 101);
label2.Name = "label2";
label2.Size = new Size(170, 15);
label2.Size = new Size(142, 15);
label2.TabIndex = 1;
label2.Text = "ID закрепленного сотрудника";
label2.Text = "Закрепленный водитель";
//
// label3
//
@ -104,9 +104,9 @@
// comboBoxDriverId
//
comboBoxDriverId.FormattingEnabled = true;
comboBoxDriverId.Location = new Point(188, 98);
comboBoxDriverId.Location = new Point(167, 98);
comboBoxDriverId.Name = "comboBoxDriverId";
comboBoxDriverId.Size = new Size(84, 23);
comboBoxDriverId.Size = new Size(105, 23);
comboBoxDriverId.TabIndex = 8;
//
// FormCar

View File

@ -44,7 +44,7 @@ namespace FuelAccounting.Forms
comboBoxCategory.DataSource = Enum.GetValues(typeof(CarCategory));
comboBoxDriverId.DataSource = driversRepository.ReadDrivers();
comboBoxDriverId.DisplayMember = "FirstName";
comboBoxDriverId.DisplayMember = "DriverName";
comboBoxDriverId.ValueMember = "Id";
}

View File

@ -84,7 +84,11 @@ namespace FuelAccounting.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _carsRepository.ReadCars();
private void LoadList()
{
dataGridViewData.DataSource = _carsRepository.ReadCars();
dataGridViewData.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -33,7 +33,7 @@ public partial class FormDirectoryReport : Form
}
if (_container.Resolve<DocReport>().CreateDoc(sfd.FileName, checkBoxCars.Checked,
checkBoxDrivers.Checked, checkBoxRoutes.Checked, checkBoxShifts.Checked))
checkBoxDrivers.Checked, checkBoxShifts.Checked, checkBoxRoutes.Checked))
{
MessageBox.Show("Документ сформирован", "Формирование документа", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

View File

@ -84,7 +84,12 @@ namespace FuelAccounting.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _driversRepository.ReadDrivers();
private void LoadList()
{
dataGridViewData.DataSource = _driversRepository.ReadDrivers();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["DriverName"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -20,7 +20,7 @@ namespace FuelAccounting.Forms
comboBoxCar.ValueMember = "Id";
comboBoxDriver.DataSource = driversRepository.ReadDrivers();
comboBoxDriver.DisplayMember = "FirstName";
comboBoxDriver.DisplayMember = "DriverName";
comboBoxDriver.ValueMember = "Id";
comboBoxShift.DataSource = shiftRepository.ReadShifts();

View File

@ -43,7 +43,12 @@ namespace FuelAccounting.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _equipageRepository.ReadEquipages();
private void LoadList()
{
dataGridViewData.DataSource = _equipageRepository.ReadEquipages();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["EquipageDate"].DefaultCellStyle.Format = "dd MMMM yyyy hh:mm";
}
private void ButtonDelete_Click(object sender, EventArgs e)
{

View File

@ -44,7 +44,7 @@
buttonAdd.Size = new Size(130, 130);
buttonAdd.TabIndex = 2;
buttonAdd.UseVisualStyleBackColor = true;
buttonAdd.Click += buttonAdd_Click;
buttonAdd.Click += ButtonAdd_Click;
//
// dataGridViewData
//

View File

@ -30,7 +30,7 @@ namespace FuelAccounting.Forms
}
}
private void buttonAdd_Click(object sender, EventArgs e)
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
@ -43,6 +43,11 @@ namespace FuelAccounting.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _refuelingRepository.ReadRefuelings();
private void LoadList()
{
dataGridViewData.DataSource = _refuelingRepository.ReadRefuelings();
dataGridViewData.Columns["Id"].Visible = false;
dataGridViewData.Columns["RefuelingDate"].DefaultCellStyle.Format = "dd.MM.yyyy hh:mm";
}
}
}

View File

@ -57,7 +57,7 @@
buttonDelete.Size = new Size(130, 130);
buttonDelete.TabIndex = 4;
buttonDelete.UseVisualStyleBackColor = true;
buttonDelete.Click += buttonDelete_Click;
buttonDelete.Click += ButtonDelete_Click;
//
// buttonUpdate
//
@ -68,7 +68,7 @@
buttonUpdate.Size = new Size(130, 130);
buttonUpdate.TabIndex = 3;
buttonUpdate.UseVisualStyleBackColor = true;
buttonUpdate.Click += buttonUpdate_Click;
buttonUpdate.Click += ButtonUpdate_Click;
//
// buttonAdd
//
@ -79,7 +79,7 @@
buttonAdd.Size = new Size(130, 130);
buttonAdd.TabIndex = 2;
buttonAdd.UseVisualStyleBackColor = true;
buttonAdd.Click += buttonAdd_Click;
buttonAdd.Click += ButtonAdd_Click;
//
// dataGridViewData
//

View File

@ -28,7 +28,7 @@ namespace FuelAccounting.Forms
}
}
private void buttonAdd_Click(object sender, EventArgs e)
private void ButtonAdd_Click(object sender, EventArgs e)
{
try
{
@ -41,7 +41,7 @@ namespace FuelAccounting.Forms
}
}
private void buttonUpdate_Click(object sender, EventArgs e)
private void ButtonUpdate_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
@ -61,7 +61,7 @@ namespace FuelAccounting.Forms
}
}
private void buttonDelete_Click(object sender, EventArgs e)
private void ButtonDelete_Click(object sender, EventArgs e)
{
if (!TryGetIdentifierFromSelectedRow(out var findId))
{
@ -84,7 +84,11 @@ namespace FuelAccounting.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _routeRepository.ReadRoutes();
private void LoadList()
{
dataGridViewData.DataSource = _routeRepository.ReadRoutes();
dataGridViewData.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -85,7 +85,11 @@ namespace FuelAccounting.Forms
}
}
private void LoadList() => dataGridViewData.DataSource = _shiftRepository.ReadShifts();
private void LoadList()
{
dataGridViewData.DataSource = _shiftRepository.ReadShifts();
dataGridViewData.Columns["Id"].Visible = false;
}
private bool TryGetIdentifierFromSelectedRow(out int id)
{

View File

@ -23,7 +23,7 @@ internal class ChartReport
{
new PdfBuilder(filePath)
.AddHeader("Подсчет километража")
.AddPieChart("Кол-во проезженных километров", GetData(dateTime))
.AddPieChart($"Кол-во проезженных километров {dateTime:dd.MM.yyyy}", GetData(dateTime))
.Build();
return true;
@ -38,9 +38,9 @@ internal class ChartReport
private List<(string Caption, double Value)> GetData(DateTime dateTime)
{
return _refuelingRepository
.ReadRefuelings()
.ReadRefuelings(dateForm: dateTime.Date, dateTo: dateTime.Date.AddDays(1))
.Where(x => x.RefuelingDate == dateTime.Date)
.GroupBy(x => x.CarId, (key, group) => new { Id = key, Count = group.Sum(x => x.Kilometers) })
.GroupBy(x => x.CarModel, (key, group) => new { Id = key, Count = group.Sum(x => x.Kilometers) })
.Select(x => (x.Id.ToString(), (double)x.Count))
.ToList();
}

View File

@ -69,7 +69,7 @@ internal class DocReport
["Модель", "Категория", "Id Водителя"],
.. _carsRepository
.ReadCars()
.Select(x => new string[] {x.Model, x.Category.ToString(), x.DriverID.ToString()}),
.Select(x => new string[] {x.Model, x.Category.ToString(), x.DriverName.ToString()}),
];
}

View File

@ -28,7 +28,7 @@ internal class TableReport
{
new ExcelBuilder(filePath)
.AddHeader("Сводка по автомобилям", 0, 4)
.AddParagraph("За период", 0)
.AddParagraph($"За период c {startDate:dd.MM.yyyy} по {endDate:dd.MM.yyyy}", 0)
.AddTable([15, 15, 10, 15], GetData(carId, startDate, endDate))
.Build();
@ -45,23 +45,21 @@ internal class TableReport
{
// Получение данных об экипажах
var equipageData = _equipageRepository
.ReadEquipages()
.Where(x => x.EquipageDate >= startDate && x.EquipageDate <= endDate && x.CarId == carId)
.ReadEquipages(dateForm: startDate, dateTo: endDate, carId: carId)
.Select(x => new
{
CarId = x.CarId,
Driver = x.DriverId.ToString(),
x.CarModel,
Driver = x.DriverName.ToString(),
Liters = 0.0, // Данные о заправке отсутствуют
Date = x.EquipageDate
});
// Получение данных о заправках
var refuelingData = _refuelingRepository
.ReadRefuelings()
.Where(x => x.RefuelingDate >= startDate && x.RefuelingDate <= endDate && x.CarId == carId)
.ReadRefuelings(dateForm: startDate, dateTo: endDate, carId: carId)
.Select(x => new
{
x.CarId,
x.CarModel,
Driver = string.Empty, // Данные о водителе отсутствуют
Liters = (double)x.LitersSpent,
Date = x.RefuelingDate
@ -70,10 +68,10 @@ internal class TableReport
// Объединение данных об экипажах и заправках
var mergedData = equipageData
.Union(refuelingData)
.GroupBy(x => new { x.CarId, x.Date }) // Группировка по дате и машине
.GroupBy(x => new { x.CarModel, x.Date }) // Группировка по дате и машине
.Select(g => new
{
g.Key.CarId,
g.Key.CarModel,
Driver = string.Join(", ", g.Select(x => x.Driver).Where(d => !string.IsNullOrEmpty(d))),
Liters = g.Sum(x => x.Liters),
g.Key.Date
@ -85,7 +83,7 @@ internal class TableReport
.Union(
mergedData.Select(x => new string[]
{
x.CarId.ToString(),
x.CarModel,
x.Driver,
x.Liters.ToString("F2"), // Форматирование до 2-х знаков после запятой
x.Date.ToString("dd.MM.yyyy") // Форматирование даты

View File

@ -111,12 +111,13 @@ WHERE id = @id";
{
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT
id,
model,
category,
driver_id AS DriverID
FROM Cars";
SELECT
c.id,
c.model,
c.category,
CONCAT(d.first_name, ' ', d.last_name) AS DriverName
FROM Cars c
LEFT JOIN Drivers d on d.id = c.driver_id";
var cars = connection.Query<Car>(querySelect);
_logger.LogDebug("Найденные объекты: {json}", JsonConvert.SerializeObject(cars));
return cars;

View File

@ -79,17 +79,72 @@ WHERE id = @id";
_logger.LogInformation("Получение всех объектов");
try
{
var builder = new QueryBuilder();
if (dateForm.HasValue)
{
builder.AddCondition("e.equipage_date >= @dateForm");
}
if (dateTo.HasValue)
{
builder.AddCondition("e.equipage_date <= @dateTo");
}
if (carId.HasValue)
{
builder.AddCondition("e.car_id = @carId");
}
if (driverId.HasValue)
{
builder.AddCondition("e.driver_id >= @driverId");
}
if (shiftId.HasValue)
{
builder.AddCondition("e.shift_id <= @shiftId");
}
if (routeId.HasValue)
{
builder.AddCondition("re.route_id = @routeId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
SELECT e.id, e.car_id AS CarId, e.driver_id AS DriverId, e.shift_id AS ShiftId,
e.equipage_date AS EquipageDate, re.route_id AS RouteId, re.count AS Count
var querySelect = $@"
SELECT
e.id,
c.model AS CarModel,
CONCAT(d.first_name, ' ', last_name) AS DriverName,
s.description AS ShiftDescription,
e.equipage_date AS EquipageDate,
re.route_id AS RouteId,
r.description AS RouteDescription,
re.count AS Count
FROM Equipage e
INNER JOIN RoutesEquipage re ON re.equipage_id = e.id";
var equipages = connection.Query<TempRoutesEquipage>(querySelect);
INNER JOIN RoutesEquipage re ON re.equipage_id = e.id
LEFT JOIN Cars c on c.id = e.car_id
LEFT JOIN Drivers d on d.id = e.driver_id
LEFT JOIN Shift s on s.id = e.shift_id
LEFT JOIN Routes r on r.id = re.route_id
{builder.Build()}";
var equipageDict = new Dictionary<int, List<RoutesEqipage>>();
var equipages = connection.Query<Equipage, RoutesEqipage, Equipage>(querySelect,
(equip, equipages) =>
{
if (!equipageDict.TryGetValue(equip.Id, out var re))
{
re = [];
equipageDict.Add(equip.Id, re);
}
re.Add(equipages);
return equip;
}, splitOn: "RouteId", param: new {dateForm, dateTo, carId, driverId, shiftId, routeId});
_logger.LogDebug("Найденные объекты: {json}", JsonConvert.SerializeObject(equipages));
return equipages.GroupBy(x => x.Id, y => y,
(key, value) => Equipage.CreateOperation(value.First(),
value.Select(z => RoutesEqipage.CreateElement(0, z.RouteId, z.CarId)))).ToList();
return equipageDict.Select(x =>
{
var e = equipages.First(y => y.Id == x.Key);
e.SetRoutesEquipage(x.Value);
return e;
}).ToArray();
}
catch (Exception ex)
{

View File

@ -0,0 +1,35 @@
using System.Text;
namespace FuelAccounting.Repositories.Implementations;
internal class QueryBuilder
{
private readonly StringBuilder _builder;
public QueryBuilder()
{
_builder = new();
}
public QueryBuilder AddCondition(string condition)
{
if (_builder.Length > 0)
{
_builder.Append(" AND ");
}
_builder.Append(condition);
return this;
}
public string Build()
{
if (_builder.Length == 0)
{
return string.Empty;
}
return $"WHERE {_builder}";
}
}

View File

@ -42,17 +42,33 @@ VALUES (@CarId, @Kilometers, @LitersSpent, @TypeOfFuel, @RefuelingDate)";
_logger.LogInformation("Получение всех объектов");
try
{
var builder = new QueryBuilder();
if (dateForm.HasValue)
{
builder.AddCondition("r.refueling_date >= @dateForm");
}
if (dateTo.HasValue)
{
builder.AddCondition("r.refueling_date <= @dateTo");
}
if (carId.HasValue)
{
builder.AddCondition("r.car_id = @carId");
}
using var connection = new NpgsqlConnection(_connectionString.ConnectionString);
var querySelect = @"
var querySelect = $@"
SELECT
id,
car_id AS CarId,
km AS Kilometers,
liters_spent AS LitersSpent,
type_of_fuel AS TypeOfFuel,
refueling_date AS RefuelingDate
FROM Refueling";
var refuelings = connection.Query<Refueling>(querySelect);
r.id,
c.model AS CarModel,
r.km AS Kilometers,
r.liters_spent AS LitersSpent,
r.type_of_fuel AS TypeOfFuel,
r.refueling_date AS RefuelingDate
FROM Refueling r
LEFT JOIN Cars c on c.id = r.car_id
{builder.Build()}";
var refuelings = connection.Query<Refueling>(querySelect, new { dateForm, dateTo, carId });
_logger.LogDebug("Найденные объекты: {json}", JsonConvert.SerializeObject(refuelings));
return refuelings;
}